package com.uinnova.product.eam.service.cj.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.binary.core.exception.BinaryException;
import com.uinnova.product.eam.model.cj.domain.*;
import com.uinnova.product.eam.model.cj.enums.ChapterDataTypeEnum;
import com.uinnova.product.eam.model.cj.enums.PlanSharePermissionEnum;
import com.uinnova.product.eam.model.cj.enums.PlanStatusEnum;
import com.uinnova.product.eam.model.cj.enums.TableContentTypeEnum;
import com.uinnova.product.eam.model.cj.request.PlanChapterInstanceAddRequest;
import com.uinnova.product.eam.model.cj.request.PlanChapterInstanceMoveRequest;
import com.uinnova.product.eam.model.cj.vo.*;
import com.uinnova.product.eam.model.constants.Constants;
import com.uinnova.product.eam.service.FxDiagramSvc;
import com.uinnova.product.eam.service.cj.dao.*;
import com.uinnova.product.eam.service.cj.service.*;
import com.uinnova.product.eam.service.exception.BusinessException;
import com.uinnova.project.api.diagram.v2.client.ESDiagramApiClient;
import com.uinnova.project.base.diagram.comm.model.ESDiagram;
import com.uino.bean.permission.business.UserInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
import com.binary.core.util.BinaryUtils;
import com.binary.jdbc.Page;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Table;
import com.uinnova.product.eam.model.asset.EamReleaseHistoryDTO;
import com.uinnova.product.eam.model.vo.ReleaseModuleDiagramVO;
import com.uino.api.client.permission.IUserApiSvc;
import com.uino.bean.permission.base.SysUser;
import com.uino.bean.permission.query.CSysUser;
import com.uino.dao.util.ESUtil;
import com.uino.util.cache.ICacheService;
import com.uino.util.sys.SysUtil;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 方案章节实例service实现
 *
 * @author zhaoxin
 */
@Service
@Slf4j
public class PlanChapterInstanceServiceImpl implements PlanChapterInstanceService {

    @Resource
    private PlanDesignInstanceDao planDesignInstanceDao;

    @Resource
    private PlanChapterInstanceDao planChapterInstanceDao;

    @Resource
    private PlanTemplateChapterService planTemplateChapterService;

    @Resource
    private ChapterContextDao chapterContextDao;

    @Resource
    private ChapterContextService chapterContextService;

    @Resource
    @Lazy
    private PlanDesignInstanceService planDesignInstanceService;

    @Resource
    private PlanArtifactService planArtifactService;
    @Autowired
    private CJResourceDaoService cjResourceDaoService;

    @Resource
    private ICacheService iCacheService;

    @Resource(name = "userApiSvcLocal")
    private IUserApiSvc userApiSvc;

    @Resource
    private PlanArtifactDao planArtifactDao;

    @Resource
    private ModuleDiagramVersionRelationDao moduleDiagramVersionRelationDao;

    @Resource
    private DeliverableTemplateService deliverableTemplateService;

    @Resource
    private PlanModuleDeleteService planModuleDeleteService;

    @Resource
    private ESDiagramApiClient diagramApiClient;

    @Resource
    private FxDiagramSvc fxDiagramSvc;

    @Resource
    private PlanChapterCollaborateService planChapterCollaborateService;

    @Resource
    private ShareService shareService;

    /**
     * 新增章节
     */
    @Override
    public Long addChapter(PlanChapterInstanceAddRequest request) {

        SysUser userInfo = SysUtil.getCurrentUserInfo();
        long dateTime = ESUtil.getNumberDateTime(new Date());

        PlanDesignInstance planDesignInstance = planDesignInstanceService.getPlanDesignInstance(request.getPlanId());
        if (planDesignInstance == null) {
            throw new BusinessException("获取方案错误");
        }
        if (!Objects.equals(userInfo.getLoginCode(), planDesignInstance.getCreatorCode())) {
            List<PlanDesignShareRecord> shareRecordList = shareService.getByPlanId(planDesignInstance.getId());
            if (!CollectionUtils.isEmpty(shareRecordList)) {
                Map<String, Integer> shareRecordMap = shareRecordList.stream().collect(Collectors.toMap(PlanDesignShareRecord::getSharedLoginCode, PlanDesignShareRecord::getPermission));
                if (shareRecordMap == null || shareRecordMap.get(userInfo.getLoginCode()) == null
                        || (!Objects.equals(shareRecordMap.get(userInfo.getLoginCode()), 1)
                        && !Objects.equals(shareRecordMap.get(userInfo.getLoginCode()), 2)
                        && !Objects.equals(shareRecordMap.get(userInfo.getLoginCode()), 4))) {
                    throw new BusinessException("暂无权限操作方案!");
                }
            } else {
                throw new BusinessException("暂无权限操作方案!");
            }
        }

        // 章节基本信息
        ChapterInstance chapter = new ChapterInstance();

        chapter.setId(ESUtil.getUUID());
        chapter.setIsFromTemplate(false);
        chapter.setName(request.getName());
        chapter.setExpand(true);
        chapter.setRequired(false);
        chapter.setParentId(request.getParentId());
        chapter.setPlanId(request.getPlanId());
        chapter.setCreatorCode(userInfo.getLoginCode());
        chapter.setCreatorName(userInfo.getUserName());
        chapter.setCreateTime(dateTime);
        chapter.setDeleted(false);
        chapter.setBusinessId(String.valueOf(ESUtil.getUUID()));
        chapter.setVersion(String.valueOf(ESUtil.getUUID()));
        chapter.setStatus(Constants.DRAFT);
        setOrderIdAndLevel(chapter);

        // 章节context
        ChapterContext context = ChapterContext.builder()
                .id(chapter.getId())
                .planId(chapter.getPlanId())
                .chapterDesc("")
                .userAddContent(true)
                .remark("")
                .businessId(String.valueOf(ESUtil.getUUID()))
                .version(String.valueOf(ESUtil.getUUID()))
                .status(Constants.DRAFT)
                .moduleList(new LinkedList<>()).build();

        planChapterInstanceDao.saveOrUpdate(chapter);
        chapterContextDao.saveOrUpdate(context);

        // 重排序
        setOrderId(request.getIndex(), chapter, chapter.getParentId());
        planChapterInstanceDao.saveOrUpdate(chapter);
        planDesignInstanceService.updateModifyTime(chapter.getPlanId());
        refreshSort(chapter.getParentId(), chapter.getPlanId());
        return chapter.getId();

    }

    @Override
    public Integer saveOrUpdateBatch(List<ChapterInstance> chapterInstanceList) {
        return planChapterInstanceDao.saveOrUpdateBatch(chapterInstanceList);
    }

    /**
     * 初始化章节
     *
     * @param planId     方案id
     * @param templateId 方案模板id
     */
    @Override
    public void initChapter(Long planId, Long templateId) {
        if (templateId == null) {
            templateId = planDesignInstanceDao.getById(planId).getTemplateId();
            if (templateId == null) {
                throw new BusinessException("方案初始化失败，没有指定模板");
            }
        }

        PlanTemplateChapter planTemplateChapter = new PlanTemplateChapter();
        planTemplateChapter.setPlanTemplateId(templateId);
        List<PlanTemplateChapterTreeVo> planTemplateChapterList = planTemplateChapterService
                .findPlanTemplateChapterList(planTemplateChapter);

        if (!BinaryUtils.isEmpty(planTemplateChapterList)) {
            List<ChapterInstance> chapterList = new LinkedList<>();
            List<ChapterContext> contextList = new LinkedList<>();

            createChapter(chapterList, contextList, planTemplateChapterList, planId, ESUtil.getNumberDateTime(),
                    SysUtil.getCurrentUserInfo());

            planChapterInstanceDao.saveOrUpdateBatch(chapterList);
            chapterContextDao.saveOrUpdateBatch(contextList);
        }
    }

    /**
     * 方案查找章节列表
     *
     * @param planId 方案id
     * @return 方案列表 树形
     */
    @Override
    public List<PlanChapterVO> getChapterList(Long planId) {
        BoolQueryBuilder query = QueryBuilders.boolQuery();
        query.must(QueryBuilders.termQuery("planId", planId));
        query.must(QueryBuilders.termQuery("deleted", false));

        List<ChapterInstance> listByQuery = planChapterInstanceDao.getListByQuery(query);

        return BinaryUtils.isEmpty(listByQuery) ? Collections.emptyList() : createChapterVO(listByQuery, 0L, false);

    }

    @Override
    public List<ChapterInstance> getChapterByPlanId(Long planId) {
        BoolQueryBuilder query = QueryBuilders.boolQuery();
        query.must(QueryBuilders.termQuery("planId", planId));
        query.must(QueryBuilders.termQuery("deleted", false));

        List<ChapterInstance> result = planChapterInstanceDao.getListByQuery(query);

        return BinaryUtils.isEmpty(result) ? Collections.emptyList() : result;

    }

    @Override
    public List<ChapterInstance> findPlanChapterList(Long planId) {
        if (planId == null) {
            throw new BusinessException("方案主键不能为空!");
        }
        BoolQueryBuilder query = QueryBuilders.boolQuery();
        query.must(QueryBuilders.termQuery("planId", planId));
        query.must(QueryBuilders.termQuery("deleted", false));
        return planChapterInstanceDao.getListByQuery(query);
    }

    /**
     * 方案章节移动
     *
     * @param request {@link PlanChapterInstanceMoveRequest}
     */
    @Override
    public void move(PlanChapterInstanceMoveRequest request) {
        ChapterInstance initChapter = planChapterInstanceDao.getById(request.getId());
        ChapterInstance targetChapter = planChapterInstanceDao.getById(request.getTargetId());
        if (Objects.equals(initChapter.getParentId(), targetChapter.getParentId())
                && (Objects.equals(request.getSign(), 1) || Objects.equals(request.getSign(), -1))) {
            // 平级移动
            handlerMoveIndex(initChapter.getPlanId(), initChapter.getParentId(), request);
            setOrderId(request.getIndex(), initChapter, initChapter.getParentId());
            planChapterInstanceDao.saveOrUpdate(initChapter);
            planDesignInstanceService.updateModifyTime(initChapter.getPlanId());
            refreshSort(initChapter.getParentId(), initChapter.getPlanId());
        } else {
            // 移动到其他章节下
            if (Objects.equals(request.getSign(), 1) || Objects.equals(request.getSign(), -1)) {
                request.setParentId(targetChapter.getParentId());
                handlerMoveIndex(initChapter.getPlanId(), targetChapter.getParentId(), request);
            } else if (Objects.equals(request.getSign(), 0)) {
                request.setParentId(request.getTargetId());
                request.setIndex(0);
            } else {
                throw new BusinessException("位置标识输入错误!");
            }

            Long sourceParentId = initChapter.getParentId();
            setOrderId(request.getIndex(), initChapter, request.getParentId());
            if (request.getParentId() == 0) {
                initChapter.setLevel(1);
            } else {
                ChapterInstance chapterInstance = planChapterInstanceDao.getById(request.getParentId());
                initChapter.setLevel(chapterInstance.getLevel() + 1);
            }
            initChapter.setParentId(request.getParentId());
            planChapterInstanceDao.saveOrUpdate(initChapter);
            planDesignInstanceService.updateModifyTime(initChapter.getPlanId());
            refreshSort(sourceParentId, initChapter.getPlanId());
            refreshSort(request.getParentId(), initChapter.getPlanId());
            if (initChapter.getIsFromTemplate()) {
                SysUser sysUser = SysUtil.getCurrentUserInfo();
                PlanModuleDelete planModuleDelete = new PlanModuleDelete();
                planModuleDelete.setPlanId(initChapter.getPlanId());
                planModuleDelete.setTemplateChapterId(initChapter.getTemplateId());
                planModuleDeleteService.addPlanModule(planModuleDelete, sysUser);
            }
        }
    }

    /**
     * 封装移动章节的索引位置
     * @param request
     */
    private void handlerMoveIndex(Long planId, Long chapterParentId, PlanChapterInstanceMoveRequest request) {
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        queryBuilder.must(QueryBuilders.termQuery("parentId", chapterParentId));
        queryBuilder.must(QueryBuilders.termQuery("planId", planId));
        queryBuilder.must(QueryBuilders.termQuery("deleted", false));
        long count = planChapterInstanceDao.countByCondition(queryBuilder);
        Page<ChapterInstance> chapterPage = planChapterInstanceDao.getSortListByQuery(1, (int) count, queryBuilder, "orderId", true);
        if (chapterPage == null || CollectionUtils.isEmpty(chapterPage.getData())) {
            request.setIndex(0);
        } else {
            List<Long> chapterIds = chapterPage.getData().stream().map(chapter -> chapter.getId()).collect(Collectors.toList());
            int targetIndex = chapterIds.indexOf(request.getTargetId());
            if (chapterIds.contains(request.getId())) {
                int initIndex = chapterIds.indexOf(request.getId());
                if (Objects.equals(request.getSign(), -1)) {
                    if (targetIndex > initIndex) {
                        if (targetIndex - 1 < 0) {
                            request.setIndex(0);
                        } else {
                            request.setIndex(targetIndex - 1);
                        }
                    } else {
                        request.setIndex(targetIndex);
                    }
                } else {
                    if (targetIndex < initIndex) {
                        request.setIndex(targetIndex + 1);
                    } else {
                        request.setIndex(targetIndex);
                    }
                }
            } else {
                if (Objects.equals(request.getSign(), -1)) {
                    if (targetIndex - 1 < 0) {
                        request.setIndex(0);
                    } else {
                        request.setIndex(targetIndex);
                    }
                } else {
                    request.setIndex(targetIndex + 1);
                }
            }
        }
    }

    /**
     * 方案章节复制
     * <p>description：复制给定id的章节内容</p>
     *
     * @param map 参数， 原章节id， 新章节名称newName
     */
    @Override
    public Long copy(Map<String, Object> map) {
        Long newChapterId = ESUtil.getUUID();

        Long referenceId = (Long) map.get("id");
        String inputName = Objects.toString(map.get("newName"), "");
        ChapterInstance chapter = planChapterInstanceDao.getById(referenceId);
        chapter.setIsFromTemplate(false);
        chapter.setRequired(false);
        chapter.setId(newChapterId);

        if (BinaryUtils.isEmpty(inputName)) {
            String formatName = String.format("%scopy", chapter.getName());
            chapter.setName (formatName);
        } else {
            chapter.setName(inputName);
        }

        ChapterContext context = chapterContextDao.getById(referenceId);
        context.setId(newChapterId);

        Map<Long, Long> moduleIdMap = new HashMap<>();
        List<ContextModule> moduleList = context.getModuleList();
        if (!CollectionUtils.isEmpty(moduleList)) {
            moduleList.forEach(contextModule -> {
                PlanTemplateChapterData moduleDefinition = contextModule.getModuleDefinition();
                long uuid = ESUtil.getUUID();
                if (Objects.equals(moduleDefinition.getType(), 1)) {
                    moduleIdMap.put(uuid, contextModule.getId());
                }

                contextModule.setId(uuid);
                moduleDefinition.setId(uuid);
                contextModule.setIsFromTemplate(false);
            });
        }

        context.setBusinessId(String.valueOf(ESUtil.getUUID()));
        context.setVersion(String.valueOf(ESUtil.getUUID()));
        context.setStatus(Constants.DRAFT);
        planChapterInstanceDao.saveOrUpdate(chapter);
        chapterContextDao.saveOrUpdate(context);

        List<PlanArtifact> planArtifactList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(context.getModuleList())) {
            context.getModuleList().forEach(module -> {
                PlanTemplateChapterData moduleDefinition = module.getModuleDefinition();
                if (moduleDefinition != null && Objects.equals(moduleDefinition.getType(), 1)) {
                    PlanArtifact subPlanArtifact = new PlanArtifact();
                    subPlanArtifact.setPlanId(chapter.getPlanId());
                    subPlanArtifact.setChapterId(referenceId);
                    subPlanArtifact.setModuleId(moduleIdMap.get(module.getId()));
                    subPlanArtifact.setStatus(1);
                    List<PlanArtifact> subPlanArtifactList = planArtifactService.findPlanArtifactList(subPlanArtifact);
                    PlanArtifact referencePlanArtifact = null;
                    if (!CollectionUtils.isEmpty(subPlanArtifactList)) {
                        referencePlanArtifact = subPlanArtifactList.get(0);
                    }
                    PlanArtifact planArtifact = new PlanArtifact();
                    planArtifact.setPlanId(chapter.getPlanId());
                    planArtifact.setChapterId(newChapterId);
                    planArtifact.setModuleId(module.getId());
                    planArtifact.setDiagramProductType(moduleDefinition.getDiagramProductType());
                    if (referencePlanArtifact != null) {
                        planArtifact.setDiagramId(referencePlanArtifact.getDiagramId());
                        planArtifact.setReleaseDiagramId(referencePlanArtifact.getReleaseDiagramId());
                        planArtifact.setVersion(referencePlanArtifact.getVersion());
                    }
                    planArtifact.setStatus(1);
                    planArtifactList.add(planArtifact);
                }
            });
        }
        // 新增方案关联制品
        PlanArtifact planArtifact = new PlanArtifact();
        planArtifact.setPlanId(chapter.getPlanId());
        planArtifact.setChapterId(newChapterId);
        planArtifactService.removePlanArtifact(planArtifact);
        if (!CollectionUtils.isEmpty(planArtifactList)) {
            planArtifactService.savePlanArtifact(planArtifactList);
        }

        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery()
                .must(QueryBuilders.termQuery("parentId", chapter.getParentId()))
                .must(QueryBuilders.termQuery("planId", chapter.getPlanId()))
                .must(QueryBuilders.termQuery("deleted", false));

        List<ChapterInstance> list = planChapterInstanceDao.getSortListByQuery(1, 3000,
                boolQueryBuilder, "orderId", true).getData();

        // 新章节的索引
        int index = 0;
        for (ChapterInstance instance : list) {
            if (instance.getId().equals(referenceId)) {
                index++;
                break;
            }
            index++;
        }

        setOrderId(index, chapter, chapter.getParentId());
        planChapterInstanceDao.saveOrUpdate(chapter);
        refreshSort(chapter.getParentId(), chapter.getPlanId());

        // 复制子章节
        ChapterInstance newChapterInfo = planChapterInstanceDao.getById(chapter.getId());
        BoolQueryBuilder subQueryBuilder = QueryBuilders.boolQuery();
        subQueryBuilder.must(QueryBuilders.termQuery("parentId", referenceId));
        subQueryBuilder.must(QueryBuilders.termQuery("planId", chapter.getPlanId()));
        subQueryBuilder.must(QueryBuilders.termQuery("deleted", false));
        long count = planChapterInstanceDao.countByCondition(subQueryBuilder);
        Page<ChapterInstance> subChapterPage = planChapterInstanceDao.getSortListByQuery(1, (int)count, subQueryBuilder, "orderId", true);
        if (subChapterPage != null && !CollectionUtils.isEmpty(subChapterPage.getData())) {
            SysUser sysUser = SysUtil.getCurrentUserInfo();
            List<ChapterInstance> subChapterList = subChapterPage.getData();
            for (int i = 0; i < subChapterList.size(); i++) {
                // 新增子章节
                long subChapterId = ESUtil.getUUID();
                ChapterInstance newChapter = new ChapterInstance();
                BeanUtils.copyProperties(subChapterList.get(i), newChapter);
                newChapter.setId(subChapterId);
                newChapter.setBusinessId(String.valueOf(ESUtil.getUUID()));
                newChapter.setVersion(String.valueOf(ESUtil.getUUID()));
                newChapter.setStatus(Constants.DRAFT);
                newChapter.setParentId(newChapterInfo.getId());
                newChapter.setSerialNum(newChapterInfo.getSerialNum() + "." + (i + 1));
                newChapter.setIsFromTemplate(false);
                newChapter.setRequired(false);
                newChapter.setCreatorName(sysUser.getUserName());
                newChapter.setCreateTime(ESUtil.getNumberDateTime());
                newChapter.setModifierCode(sysUser.getLoginCode());
                newChapter.setModifyTime(ESUtil.getNumberDateTime());
                newChapter.setModifierName(sysUser.getUserName());
                newChapter.setDomainId(sysUser.getDomainId());
                planChapterInstanceDao.saveOrUpdate(newChapter);

                // 新增子章节内容块
                ChapterContext subContext = chapterContextDao.getById(subChapterList.get(i).getId());
                Map<Long, Long> subModuleIdMap = new HashMap<>();
                List<ContextModule> subModuleList = subContext.getModuleList();
                if (!CollectionUtils.isEmpty(subModuleList)) {
                    subModuleList.forEach(contextModule -> {
                        PlanTemplateChapterData moduleDefinition = contextModule.getModuleDefinition();
                        long uuid = ESUtil.getUUID();
                        if (Objects.equals(moduleDefinition.getType(), 1)) {
                            subModuleIdMap.put(contextModule.getId(), uuid);
                        }

                        contextModule.setId(uuid);
                        moduleDefinition.setId(uuid);
                        contextModule.setIsFromTemplate(false);
                    });
                }

                subContext.setId(subChapterId);
                subContext.setBusinessId(String.valueOf(ESUtil.getUUID()));
                subContext.setVersion(String.valueOf(ESUtil.getUUID()));
                subContext.setStatus(Constants.DRAFT);
                chapterContextDao.saveOrUpdate(subContext);

                // 新增方案关联制品
                PlanArtifact subPlanArtifact = new PlanArtifact();
                subPlanArtifact.setPlanId(newChapterInfo.getPlanId());
                subPlanArtifact.setChapterId(subChapterList.get(i).getId());
                subPlanArtifact.setStatus(1);
                List<PlanArtifact> subPlanArtifactList = planArtifactService.findPlanArtifactList(subPlanArtifact);
                if (!CollectionUtils.isEmpty(subPlanArtifactList)) {
                    List<PlanArtifact> newSubPlanArtifactList = new ArrayList<>();
                    for (PlanArtifact subArtifact : subPlanArtifactList) {
                        PlanArtifact newPlanArtifact = new PlanArtifact();
                        BeanUtils.copyProperties(subArtifact, newPlanArtifact);
                        newPlanArtifact.setId(ESUtil.getUUID());
                        newPlanArtifact.setChapterId(subChapterId);
                        if (subArtifact.getModuleId() != null && subModuleIdMap.get(subArtifact.getModuleId()) != null) {
                            newPlanArtifact.setModuleId(subModuleIdMap.get(subArtifact.getModuleId()));
                        } else {
                            continue;
                        }
                        newPlanArtifact.setCreatorName(sysUser.getUserName());
                        newPlanArtifact.setCreateTime(ESUtil.getNumberDateTime());
                        newPlanArtifact.setModifierCode(sysUser.getLoginCode());
                        newPlanArtifact.setModifyTime(ESUtil.getNumberDateTime());
                        newPlanArtifact.setModifierName(sysUser.getUserName());
                        newPlanArtifact.setDomainId(sysUser.getDomainId());
                        newSubPlanArtifactList.add(newPlanArtifact);
                    }
                    planArtifactService.savePlanArtifact(newSubPlanArtifactList);
                }

                // 如果还有子章节，继续复制
                handleChapter(newChapterInfo.getPlanId(), subChapterList.get(i).getId(), newChapter.getId(), newChapter.getSerialNum());
            }
        }

        return newChapterId;
    }

    /**
     * 递归处理子章节
     * @param planId 方案id
     * @param oldParentId 被复制的章节父id
     * @param newParentId 已复制的章节父id
     * @param newSerialNum 已复制的章节序号
     */
    private void handleChapter(Long planId, Long oldParentId, Long newParentId, String newSerialNum) {
        BoolQueryBuilder subQueryBuilder = QueryBuilders.boolQuery();
        subQueryBuilder.must(QueryBuilders.termQuery("parentId", oldParentId));
        subQueryBuilder.must(QueryBuilders.termQuery("planId", planId));
        subQueryBuilder.must(QueryBuilders.termQuery("deleted", false));
        long count = planChapterInstanceDao.countByCondition(subQueryBuilder);
        Page<ChapterInstance> subChapterPage = planChapterInstanceDao.getSortListByQuery(1, (int)count, subQueryBuilder, "orderId", true);
        if (subChapterPage != null && !CollectionUtils.isEmpty(subChapterPage.getData())) {
            SysUser sysUser = SysUtil.getCurrentUserInfo();
            List<ChapterInstance> subChapterList = subChapterPage.getData();
            for (int i = 0; i < subChapterList.size(); i++) {
                // 新增子章节
                long subChapterId = ESUtil.getUUID();
                ChapterInstance newChapter = new ChapterInstance();
                BeanUtils.copyProperties(subChapterList.get(i), newChapter);
                newChapter.setId(subChapterId);
                newChapter.setBusinessId(String.valueOf(ESUtil.getUUID()));
                newChapter.setVersion(String.valueOf(ESUtil.getUUID()));
                newChapter.setStatus(Constants.DRAFT);
                newChapter.setParentId(newParentId);
                newChapter.setSerialNum(newSerialNum + "." + (i + 1));
                newChapter.setIsFromTemplate(false);
                newChapter.setRequired(false);
                newChapter.setCreatorName(sysUser.getUserName());
                newChapter.setCreateTime(ESUtil.getNumberDateTime());
                newChapter.setModifierCode(sysUser.getLoginCode());
                newChapter.setModifyTime(ESUtil.getNumberDateTime());
                newChapter.setModifierName(sysUser.getUserName());
                newChapter.setDomainId(sysUser.getDomainId());
                planChapterInstanceDao.saveOrUpdate(newChapter);

                // 新增子章节内容块
                ChapterContext subContext = chapterContextDao.getById(subChapterList.get(i).getId());
                Map<Long, Long> subModuleIdMap = new HashMap<>();
                List<ContextModule> subModuleList = subContext.getModuleList();
                if (!CollectionUtils.isEmpty(subModuleList)) {
                    subModuleList.forEach(contextModule -> {
                        PlanTemplateChapterData moduleDefinition = contextModule.getModuleDefinition();
                        long uuid = ESUtil.getUUID();
                        if (Objects.equals(moduleDefinition.getType(), 1)) {
                            subModuleIdMap.put(contextModule.getId(), uuid);
                        }

                        contextModule.setId(uuid);
                        moduleDefinition.setId(uuid);
                        contextModule.setIsFromTemplate(false);
                    });
                }

                subContext.setId(subChapterId);
                subContext.setBusinessId(String.valueOf(ESUtil.getUUID()));
                subContext.setVersion(String.valueOf(ESUtil.getUUID()));
                subContext.setStatus(Constants.DRAFT);
                chapterContextDao.saveOrUpdate(subContext);

                // 新增方案关联制品
                PlanArtifact subPlanArtifact = new PlanArtifact();
                subPlanArtifact.setPlanId(planId);
                subPlanArtifact.setChapterId(subChapterList.get(i).getId());
                subPlanArtifact.setStatus(1);
                List<PlanArtifact> subPlanArtifactList = planArtifactService.findPlanArtifactList(subPlanArtifact);
                if (!CollectionUtils.isEmpty(subPlanArtifactList)) {
                    List<PlanArtifact> newSubPlanArtifactList = new ArrayList<>();
                    for (PlanArtifact subArtifact : subPlanArtifactList) {
                        PlanArtifact newPlanArtifact = new PlanArtifact();
                        BeanUtils.copyProperties(subArtifact, newPlanArtifact);
                        newPlanArtifact.setId(ESUtil.getUUID());
                        newPlanArtifact.setChapterId(subChapterId);
                        if (subArtifact.getModuleId() != null && subModuleIdMap.get(subArtifact.getModuleId()) != null) {
                            newPlanArtifact.setModuleId(subModuleIdMap.get(subArtifact.getModuleId()));
                        } else {
                            continue;
                        }
                        newPlanArtifact.setCreatorName(sysUser.getUserName());
                        newPlanArtifact.setCreateTime(ESUtil.getNumberDateTime());
                        newPlanArtifact.setModifierCode(sysUser.getLoginCode());
                        newPlanArtifact.setModifyTime(ESUtil.getNumberDateTime());
                        newPlanArtifact.setModifierName(sysUser.getUserName());
                        newPlanArtifact.setDomainId(sysUser.getDomainId());
                        newSubPlanArtifactList.add(newPlanArtifact);
                    }
                    planArtifactService.savePlanArtifact(newSubPlanArtifactList);
                }

                // 如果还有子章节，继续复制
                handleChapter(planId, subChapterList.get(i).getId(), newChapter.getId(), newChapter.getSerialNum());
            }
        }
    }

    /**
     * 章节删除
     *
     * @param id 章节id
     */
    @Override
    public void deleteById(Long id) {
        SysUser sysUser = SysUtil.getCurrentUserInfo();
        if (sysUser == null || StringUtils.isEmpty(sysUser.getLoginCode())) {
            throw new BusinessException("当前用户登录已过期，请重新登录!");
        }

        ChapterInstance chapter = planChapterInstanceDao.getById(id);
        PlanDesignInstance planDesignInstance = planDesignInstanceService.getPlanDesignInstance(chapter.getPlanId());

        // 判断是否有权限操作方案
        if (!Objects.equals(sysUser.getLoginCode(), planDesignInstance.getCreatorCode())) {
            List<PlanDesignShareRecord> shareRecordList = shareService.getByPlanId(planDesignInstance.getId());
            if (!CollectionUtils.isEmpty(shareRecordList)) {
                Map<String, Integer> shareRecordMap = shareRecordList.stream().collect(Collectors.toMap(PlanDesignShareRecord::getSharedLoginCode, PlanDesignShareRecord::getPermission));
                if (shareRecordMap == null || shareRecordMap.get(sysUser.getLoginCode()) == null
                        || (!Objects.equals(shareRecordMap.get(sysUser.getLoginCode()), 1)
                        && !Objects.equals(shareRecordMap.get(sysUser.getLoginCode()), 2)
                        && !Objects.equals(shareRecordMap.get(sysUser.getLoginCode()), 4))) {
                    throw new BusinessException("暂无权限操作方案!");
                }
            } else {
                throw new BusinessException("暂无权限操作方案!");
            }
        }

        checkDel(chapter);
        doDelete(id);
        refreshSort(chapter.getParentId(), chapter.getPlanId());

        // 记录用户删除来自于模板的章节
        if (chapter.getIsFromTemplate()) {
            PlanModuleDelete planModuleDelete = new PlanModuleDelete();
            planModuleDelete.setPlanId(chapter.getPlanId());
            planModuleDelete.setTemplateChapterId(chapter.getTemplateId());
            planModuleDeleteService.addPlanModule(planModuleDelete, sysUser);
        }

        // 删除方案关联制品
        PlanArtifact planArtifact = new PlanArtifact();
        planArtifact.setPlanId(chapter.getPlanId());
        planArtifact.setChapterId(chapter.getId());
        planArtifactService.removePlanArtifact(planArtifact);

        // 删除子章节
        List<ChapterInstance> subChapterList = planChapterInstanceDao.getListByQuery(QueryBuilders.boolQuery()
                .must(QueryBuilders.termQuery("planId", chapter.getPlanId()))
                .must(QueryBuilders.termQuery("parentId", id))
                .must(QueryBuilders.termQuery("deleted", false)));
        if (!CollectionUtils.isEmpty(subChapterList)) {
            for (ChapterInstance subChapter : subChapterList) {
                doDelete(subChapter.getId());

                // 记录用户删除来自于模板的章节
                if (subChapter.getIsFromTemplate()) {
                    PlanModuleDelete planModuleDelete = new PlanModuleDelete();
                    planModuleDelete.setPlanId(chapter.getPlanId());
                    planModuleDelete.setTemplateChapterId(subChapter.getTemplateId());
                    planModuleDeleteService.addPlanModule(planModuleDelete, sysUser);
                }

                // 删除方案关联制品
                PlanArtifact subPlanArtifact = new PlanArtifact();
                subPlanArtifact.setPlanId(chapter.getPlanId());
                subPlanArtifact.setChapterId(subChapter.getId());
                planArtifactService.removePlanArtifact(subPlanArtifact);

                // 递归删除子章节
                handlerDeleteChapter(chapter.getPlanId(), subChapter.getId(), sysUser);
            }
        }
    }

    private void handlerDeleteChapter(Long planId, Long parentId, SysUser sysUser) {
        // 删除子章节
        // 删除子章节
        List<ChapterInstance> subChapterList = planChapterInstanceDao.getListByQuery(QueryBuilders.boolQuery()
                .must(QueryBuilders.termQuery("planId", planId))
                .must(QueryBuilders.termQuery("parentId", parentId))
                .must(QueryBuilders.termQuery("deleted", false)));
        if (!CollectionUtils.isEmpty(subChapterList)) {
            for (ChapterInstance subChapter : subChapterList) {
                doDelete(subChapter.getId());

                // 记录用户删除来自于模板的章节
                if (subChapter.getIsFromTemplate()) {
                    PlanModuleDelete planModuleDelete = new PlanModuleDelete();
                    planModuleDelete.setPlanId(planId);
                    planModuleDelete.setTemplateChapterId(subChapter.getTemplateId());
                    planModuleDeleteService.addPlanModule(planModuleDelete, sysUser);
                }

                // 删除方案关联制品
                PlanArtifact subPlanArtifact = new PlanArtifact();
                subPlanArtifact.setPlanId(planId);
                subPlanArtifact.setChapterId(subChapter.getId());
                planArtifactService.removePlanArtifact(subPlanArtifact);

                // 处理删除子章节
                handlerDeleteChapter(planId, subChapter.getId(), sysUser);
            }
        }
    }

    @Override
    public String getChapterSerialNum(Long planId, Long chapterId) {
        List<PlanChapterVO> chapterList = getChapterList(planId);
        //把数变成一个整体list，查找我们对应的章节的SerialNum
        List<PlanChapterVO> planChapterVOS = new ArrayList<>();
        getAllPlanChapterVo(chapterList, planChapterVOS);
        Assert.isTrue(planChapterVOS.size() != 0, "获取章节序号失败");
        List<PlanChapterVO> list =
                planChapterVOS.stream().filter(item -> item.getId().equals(chapterId)).collect(Collectors.toList());
        return list.get(0).getFullName();
    }

    private void getAllPlanChapterVo(List<PlanChapterVO> chapterList, List<PlanChapterVO> planChapterVOS) {
        if (CollectionUtils.isEmpty(chapterList)) {
            return;
        }
        List<PlanChapterVO> child = new ArrayList<>();
        for (PlanChapterVO planChapterVO : chapterList) {
            planChapterVOS.add(planChapterVO);
            child.addAll(planChapterVO.getChildChapterList());
        }
        getAllPlanChapterVo(child, planChapterVOS);
    }

    /**
     * 方案预览
     *
     * @param planId 方案id
     * @return 方案预览数据
     */
    @Override
    public PlanPreviewVO planPreview(Long planId) {
        PlanDesignInstance plan = planDesignInstanceDao.getById(planId);

        List<ChapterInstance> chapterInstanceList = planChapterInstanceDao.getListByQuery(QueryBuilders.boolQuery()
                .must(QueryBuilders.termQuery("planId", planId))
                .must(QueryBuilders.termQuery("deleted", false)));

        List<PlanChapterVO> chapterList = BinaryUtils.isEmpty(chapterInstanceList) ? Collections.emptyList() :
                createChapterVO(chapterInstanceList, 0L, true);

        return PlanPreviewVO.builder()
                .planName(plan.getName())
                .planDept("")
                .createTime(plan.getCreateTime())
                .chapterList(chapterList)
                .build();
    }

    @Override
    public ChapterInstance getPlanChapterInstance(Long planChapterId) {
        return planChapterInstanceDao.getById(planChapterId);
    }

    @Override
    public boolean lockChapter(HandlePlanChapterVO handlePlanChapterVO, SysUser sysUser) {
        String key = Constants.LOCK_CHAPTER_SET + handlePlanChapterVO.getPlanId() + Constants.COLON + handlePlanChapterVO.getChapterId() + Constants.COLON;
        String value = (String) iCacheService.getCache(key);
        if (StringUtils.isEmpty(value) && Objects.equals(handlePlanChapterVO.getLock(), 1)) {
            iCacheService.setCache(key, sysUser.getLoginCode(), 15000);
            return true;
        }
        if (Objects.equals(sysUser.getLoginCode(), value)) {
            if (handlePlanChapterVO.getLock() == 1) {
                iCacheService.setCache(key, sysUser.getLoginCode(), 15000);
            } else {
                iCacheService.delKey(key);
            }
        } else {
            if (handlePlanChapterVO.getLock() == 1) {
                String result = (String) iCacheService.getCache(key);
                if (StringUtils.isEmpty(result)) {
                    iCacheService.setCache(key, sysUser.getLoginCode(), 15000);
                } else {
                    CSysUser cdt = new CSysUser();
                    cdt.setLoginCodeEqual(value);
                    List<SysUser> sysUserList = userApiSvc.getSysUserByCdt(cdt);
                    if(!CollectionUtils.isEmpty(sysUserList)) {
                        SysUser user = sysUserList.get(0);
                        throw new BusinessException("该章节正在被[" + user.getUserName() + "]编辑!");
                    } else {
                        throw new BusinessException("该章节正在被编辑!");
                    }
                }
            }
        }
        return true;
    }

    @Override
    public Map<String,List<PlanIntroChapterVo>> getAllIntroChapterInfo(List<PlanTemplateIntroduceChapterVo> templateIntroduceChapterVos) {
        Map<String,List<PlanIntroChapterVo>> result = new LinkedHashMap<>();
        if (!CollectionUtils.isEmpty(templateIntroduceChapterVos)) {
            List<Long> planTemplateList = templateIntroduceChapterVos.stream().map(PlanTemplateIntroduceChapterVo::getPlanTemplateId).distinct().collect(Collectors.toList());
            BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
            boolQueryBuilder.must(QueryBuilders.termsQuery("templateId",planTemplateList));
            boolQueryBuilder.must(QueryBuilders.termQuery("status.keyword","published"));
            boolQueryBuilder.must(QueryBuilders.termQuery("assetsType","2"));
            List<SortBuilder<?>> sorts = new ArrayList<>();
            sorts.add(SortBuilders.fieldSort("modifyTime").order(SortOrder.ASC));
            Page<PlanDesignInstance> sortListByQuery = planDesignInstanceDao.getSortListByQuery(1, 2000, boolQueryBuilder, sorts);
            if (CollectionUtils.isEmpty(sortListByQuery.getData())) {
                return  Maps.newHashMap();
            }
            List<PlanDesignInstance> planDesignInstanceList = sortListByQuery.getData();
            Map<Long, List<PlanDesignInstance>> planMap = planDesignInstanceList.stream().collect(Collectors.groupingBy(item -> item.getTemplateId()));
            List<Long> planIdList = planDesignInstanceList.stream().map(PlanDesignInstance::getId).distinct().collect(Collectors.toList());
            List<ChapterInstance> chapterInstanceList = planChapterInstanceDao.getListByQuery(QueryBuilders.boolQuery().must(QueryBuilders.termsQuery("planId", planIdList)).mustNot(QueryBuilders.termQuery("deleted",true)));
            for (PlanTemplateIntroduceChapterVo templateIntroduceChapterVo : templateIntroduceChapterVos) {
                List<PlanDesignInstance> planDesignInstances = planMap.get(templateIntroduceChapterVo.getPlanTemplateId());
                if (null == planDesignInstances) {
                    continue;
                }
                List<PlanIntroChapterVo> planIntroChapterVoList = Lists.newArrayList();
                for (PlanDesignInstance planDesignInstance : planDesignInstances) {
                    PlanIntroChapterVo planIntroChapterVo = new PlanIntroChapterVo();
                    planIntroChapterVo.setPlanId(planDesignInstance.getId());
                    List<ChapterInstance> findAllChapterList = chapterInstanceList.stream()
                            .filter(item ->item.getIsFromTemplate().equals(true) && planDesignInstance.getId().equals(item.getPlanId()) && item.getTemplateId().equals(templateIntroduceChapterVo.getPlanTemplateChapterId())).collect(Collectors.toList());
                    for (ChapterInstance chapterInstance : findAllChapterList) {
                        planIntroChapterVo.setChapterId(chapterInstance.getId());
                        String planChapterName =  findChapterPathName(chapterInstanceList,chapterInstance,templateIntroduceChapterVo.getPlanTemplateChapterIdPath());
                        planIntroChapterVo.setPlanChapterPathName(planDesignInstance.getName() + planChapterName);
                        planIntroChapterVoList.add(planIntroChapterVo);
                    }

                }
                result.put(templateIntroduceChapterVo.getPathName(),planIntroChapterVoList);
            }
            return result;
        }
        return null;
    }

    @Override
    public List<DiagramVersionBO> findDiagramVersions(Long planId) {
        //下面是统一查询方案下面关联的已发布的视图
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(QueryBuilders.termQuery("planId",planId));
        boolQueryBuilder.must(QueryBuilders.termQuery("status",1));
        boolQueryBuilder.must(QueryBuilders.rangeQuery("version").gt(0));
        boolQueryBuilder.must(QueryBuilders.existsQuery("releaseDiagramId"));
        List<PlanArtifact> planArtifactList = planArtifactDao.getListByQuery(boolQueryBuilder);
        //封装查询视图版本对象，批量查询
        if (CollectionUtils.isEmpty(planArtifactList)) {
            return new ArrayList<>();
        }
        List<ReleaseModuleDiagramVO> releaseModuleDiagramVOS = new ArrayList<>();
        Map<String, Set<Integer>> versionsMap = new HashMap<>();
        planArtifactList.forEach(item -> incrMethod(item.getReleaseDiagramId(),item,versionsMap));
        for (Map.Entry<String, Set<Integer>> versionMap : versionsMap.entrySet()) {
            ReleaseModuleDiagramVO releaseModuleDiagramVO = new ReleaseModuleDiagramVO();
            releaseModuleDiagramVO.setDiagramId(versionMap.getKey());
            releaseModuleDiagramVO.setReleaseVersions(new ArrayList<>(versionMap.getValue()));
            releaseModuleDiagramVOS.add(releaseModuleDiagramVO);
        }
        //下面是查询视图本地版本和资产库最新版本信息
        Map<String, List<EamReleaseHistoryDTO>> diagramVersionMap = queryHistoryDiagramByIds(releaseModuleDiagramVOS);
        
        //下面封装返回数据实体类 章节id 内容块id 本地视图版本 资产库最新版本 和对用的最新视图信息
        List<DiagramVersionBO> result = new ArrayList<>();
        //先查看方案全部忽略更新的视图版本
        ModuleDiagramVersionRelation moduleDiagramVersionRelation = new ModuleDiagramVersionRelation();
        moduleDiagramVersionRelation.setPlanId(planId);
        List<ModuleDiagramVersionRelation> relationList = moduleDiagramVersionRelationDao.getListByCdt(moduleDiagramVersionRelation);
        //将我们的list转换成table类型
        Table<Long,Long,ModuleDiagramVersionRelation> relationTable = HashBasedTable.create();
        for (ModuleDiagramVersionRelation diagramVersionRelation : relationList) {
            relationTable.put(diagramVersionRelation.getChapterId(),diagramVersionRelation.getModuleId(),diagramVersionRelation);
        }
        for (PlanArtifact planArtifact : planArtifactList) {
            Set<Integer> versionCount = versionsMap.get(planArtifact.getReleaseDiagramId());
            List<EamReleaseHistoryDTO> diagramCount = diagramVersionMap.get(planArtifact.getReleaseDiagramId());
            if (CollectionUtils.isEmpty(diagramCount)) {
               continue;
            }
            if (diagramCount.size() > versionCount.size()) {
                if (!relationTable.isEmpty() || null != relationTable.get(planArtifact.getChapterId(), planArtifact.getModuleId())) {
                    ModuleDiagramVersionRelation findVersionRelation = relationTable.get(planArtifact.getChapterId(), planArtifact.getModuleId());
                    if(findVersionRelation != null && diagramCount.get(diagramCount.size()-1).getReleaseInfo().getVersionNo() == findVersionRelation.getIgnoreVersion()){
                        continue;
                    }
                }
                DiagramVersionBO diagramVersionBO = new DiagramVersionBO();
                diagramVersionBO.setChapterId(planArtifact.getChapterId());
                diagramVersionBO.setModuleId(planArtifact.getModuleId());
                diagramVersionBO.setLocalVersion(planArtifact.getVersion());
                diagramVersionBO.setEamReleaseHistoryDTO(diagramCount.get(diagramCount.size()-1));
                result.add(diagramVersionBO);
            }else if (diagramCount.size() == versionCount.size() && !CollectionUtils.isEmpty(diagramCount)) {
                Integer version = planArtifact.getVersion();
                if (diagramCount.get(diagramCount.size() - 1).getReleaseInfo().getDiagram().getReleaseVersion() == version) {
                    continue;
                }
                if (!relationTable.isEmpty()) {
                    ModuleDiagramVersionRelation findVersionRelation = relationTable.get(planArtifact.getChapterId(), planArtifact.getModuleId());
                    if(findVersionRelation != null && diagramCount.get(diagramCount.size()-1).getReleaseInfo().getVersionNo() == findVersionRelation.getIgnoreVersion()){
                        continue;
                    }
                }
                DiagramVersionBO diagramVersionBO = new DiagramVersionBO();
                diagramVersionBO.setChapterId(planArtifact.getChapterId());
                diagramVersionBO.setModuleId(planArtifact.getModuleId());
                diagramVersionBO.setLocalVersion(planArtifact.getVersion());
                diagramVersionBO.setEamReleaseHistoryDTO(diagramCount.get(diagramCount.size()-1));
                result.add(diagramVersionBO);
            }

        }
        return result;
    }

    private Map<String,List<EamReleaseHistoryDTO>> queryHistoryDiagramByIds(List<ReleaseModuleDiagramVO> releaseModuleDiagramVOs) {
        log.info("################## 初始化的查询参数：【{}】", JSONObject.toJSONString(releaseModuleDiagramVOs));
        Map<String, List<Integer>> param = new HashMap<>();     // 重组传参

        // 查询传参的diagramId中的版本号是否包含最新版本号 如果没有 手动将最新版本号设置进 releaseVersions 集合中
        List<String> diagramIds = releaseModuleDiagramVOs.stream().map(ReleaseModuleDiagramVO::getDiagramId).collect(Collectors.toList());
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(diagramIds)) {
            throw new BinaryException("参数异常，视图ID信息不能为空！");
        }
        List<ESDiagram> esDiagrams = diagramApiClient.queryDBDiagramInfoByIds(diagramIds.toArray(new String[0]));
        // 后端过滤未发布的视图数据
        esDiagrams.stream().filter(diagram -> diagram.getIsOpen() == 1).collect(Collectors.toList());
        for (ESDiagram esDiagram : esDiagrams) {
            for (ReleaseModuleDiagramVO releaseModuleDiagramVO : releaseModuleDiagramVOs) {
                // 判断当前视图ID最新版本号是否包含在传参的数组内 如果没有 手动插入
                if (esDiagram.getDEnergy().equals(releaseModuleDiagramVO.getDiagramId())) {
                    List<Integer> releaseVersions = releaseModuleDiagramVO.getReleaseVersions();        // 参数中的版本号list
                    if (!releaseModuleDiagramVO.getReleaseVersions().contains(esDiagram.getReleaseVersion())) {
                        log.info("################## 视图ID:【{}】,存在最新版本:【{}】，需要添加进参数", releaseModuleDiagramVO.getDiagramId(), esDiagram.getReleaseVersion());
                        releaseVersions.add(esDiagram.getReleaseVersion());
                    }
                    param.put(releaseModuleDiagramVO.getDiagramId(), releaseVersions);
                }
            }
        }
        log.info("################## 最终重组的查询参数：【{}】", JSONObject.toJSONString(param));

        BoolQueryBuilder query = QueryBuilders.boolQuery();
        query.must(QueryBuilders.termsQuery("dEnergy.keyword", param.keySet()));
        Page<ESDiagram> diagramPage = diagramApiClient.selectListByQuery(1, param.keySet().size(), query);
        if (diagramPage.getData().size() != param.keySet().size()) {
            throw new BinaryException("视图已经被删除，请进入编辑页面重新选择！");
        }
        return fxDiagramSvc.queryHistoryDiagramInfoByIds(param);
    }

    @Override
    public List<ChapterInstance> findChapterInstanceList(Long planId, Integer status) {
        BoolQueryBuilder query = QueryBuilders.boolQuery();
        query.must(QueryBuilders.termQuery("planId", planId));
        query.must(QueryBuilders.termQuery("deleted", false));
        if (status != null) {
            query.must(QueryBuilders.termQuery("status", status));
        }
        return planChapterInstanceDao.getListByQuery(query);
    }

    @Override
    public Boolean ignoreViewVersions(Long planId) {
        List<DiagramVersionBO> diagramVersions = this.findDiagramVersions(planId);
        if (CollectionUtils.isEmpty(diagramVersions)) {
            return true;
        }

        ModuleDiagramVersionRelation moduleDiagramVersionRelation = new ModuleDiagramVersionRelation();
        moduleDiagramVersionRelation.setPlanId(planId);
        List<ModuleDiagramVersionRelation> relationList = moduleDiagramVersionRelationDao.getListByCdt(moduleDiagramVersionRelation);
        //将我们的list转换成table类型
        Table<Long,Long,ModuleDiagramVersionRelation> relationTable = HashBasedTable.create();
        for (ModuleDiagramVersionRelation diagramVersionRelation : relationList) {
            relationTable.put(diagramVersionRelation.getChapterId(),diagramVersionRelation.getModuleId(),diagramVersionRelation);
        }

        ArrayList<ModuleDiagramVersionRelation> batchSave = Lists.newArrayList();
        for (DiagramVersionBO diagramVersion : diagramVersions) {
            if (relationTable.get(diagramVersion.getChapterId(), diagramVersion.getModuleId()) != null) {
                ModuleDiagramVersionRelation updateVersionRelation = relationTable.get(diagramVersion.getChapterId(), diagramVersion.getModuleId());
                updateVersionRelation.setDiagramId(diagramVersion.getEamReleaseHistoryDTO().getReleaseInfo().getDEnergy());
                updateVersionRelation.setIgnoreVersion(diagramVersion.getEamReleaseHistoryDTO().getReleaseInfo().getVersionNo());
                batchSave.add(updateVersionRelation);

            }else{
                ModuleDiagramVersionRelation addModuleDiagramVersionRelation = new ModuleDiagramVersionRelation();
                addModuleDiagramVersionRelation.setId(ESUtil.getUUID());
                addModuleDiagramVersionRelation.setPlanId(planId);
                addModuleDiagramVersionRelation.setChapterId(diagramVersion.getChapterId());
                addModuleDiagramVersionRelation.setModuleId(diagramVersion.getModuleId());
                addModuleDiagramVersionRelation.setDiagramId(diagramVersion.getEamReleaseHistoryDTO().getReleaseInfo().getDEnergy());
                addModuleDiagramVersionRelation.setIgnoreVersion(diagramVersion.getEamReleaseHistoryDTO().getReleaseInfo().getVersionNo());
                batchSave.add(addModuleDiagramVersionRelation);
            }
        }
        moduleDiagramVersionRelationDao.saveOrUpdateBatch(batchSave);
        return true;
    }

    @Override
    public Boolean checkPlanTemplate(Long planId) {
        if (planId == null) {
            throw new BusinessException("参数不能为空!");
        }
        PlanDesignInstance plan = planDesignInstanceDao.getById(planId);
        if (plan == null) {
            throw new BusinessException("获取方案信息异常!");
        }
        DlvrTemplateVO dlvrTemplate = deliverableTemplateService.getDlvrTemplateById(plan.getTemplateId());
        if (dlvrTemplate == null || !Objects.equals(dlvrTemplate.getStatus(), 3)) {
            return false;
        }

        SysUser sysUser = SysUtil.getCurrentUserInfo();
        if (sysUser == null || StringUtils.isEmpty(sysUser.getLoginCode())) {
            throw new BusinessException("当前登录已过期，请重新登陆!");
        }

        // 获取方案章节列表
        BoolQueryBuilder query = QueryBuilders.boolQuery();
        query.must(QueryBuilders.termQuery("planId", planId));
        query.must(QueryBuilders.termQuery("isFromTemplate", true));
        query.must(QueryBuilders.termQuery("deleted", false));
        List<ChapterInstance> chapterList = planChapterInstanceDao.getListByQuery(query);
        List<Long> chapterIdList = chapterList.stream().map(chapter -> chapter.getTemplateId()).collect(Collectors.toList());
        Map<Long, ChapterInstance> chapterInstanceInfoMap = chapterList.stream().collect(Collectors.toMap(item -> item.getTemplateId(), item -> item));

        // 获取方案模板章节数据
        List<Long> templateChapterIdList = new ArrayList<>();
        List<PlanTemplateChapter> chapterTemplateList = planTemplateChapterService.findPlanChapterList(plan.getTemplateId());
        if (!CollectionUtils.isEmpty(chapterTemplateList)) {
            templateChapterIdList = chapterTemplateList.stream().map(chapter -> chapter.getId()).collect(Collectors.toList());
        }
        if (!Objects.equals(chapterIdList.size(), templateChapterIdList.size()) || !templateChapterIdList.containsAll(chapterIdList)) {
            // 检查模板是否有新增章节
            List<Long> newTemplateChapterIdList = new ArrayList<>(templateChapterIdList);
            newTemplateChapterIdList.removeAll(chapterIdList);
            if (!CollectionUtils.isEmpty(newTemplateChapterIdList)) {
                List<PlanModuleDelete> planModuleDeleteList = planModuleDeleteService.findPlanModuleDeleteList(planId, newTemplateChapterIdList, null, sysUser.getLoginCode());
                // 说明用户没有删除部分章节
                if (planModuleDeleteList.size() < newTemplateChapterIdList.size()) {
                    return true;
                }
            }

            if (chapterIdList.size() > templateChapterIdList.size()) {
                chapterIdList.removeAll(templateChapterIdList);
                if (!CollectionUtils.isEmpty(chapterIdList)) {
                    for (Long chapterId : chapterIdList) {
                        ChapterInstance chapterInstance = chapterInstanceInfoMap.get(chapterId);
                        if (chapterInstance != null && !Objects.equals(chapterInstance.getTemplateDelete(), 1)) {
                            return true;
                        }
                    }
                }
            }

            Boolean result = handlerPlanTemplate(chapterTemplateList, chapterInstanceInfoMap, sysUser);
            if (result != null) {
                return result;
            }
        } else {
            // 模板和方案比较是否是同一层级
            for (PlanTemplateChapter planTemplateChapter: chapterTemplateList) {
                ChapterInstance chapterInstance = chapterInstanceInfoMap.get(planTemplateChapter.getId());
                if (chapterInstance.getTemplateParentId() != null && !Objects.equals(planTemplateChapter.getParentId(), chapterInstance.getTemplateParentId())) {
                    // 关联模板的方案章节已删除，模块不再进行比对
                    PlanModuleDelete planModule = new PlanModuleDelete();
                    planModule.setPlanId(chapterInstance.getPlanId());
                    planModule.setTemplateChapterId(chapterInstance.getTemplateId());
                    PlanModuleDelete planModuleDelete = planModuleDeleteService.getPlanModuleDelete(planModule, sysUser);
                    if (planModuleDelete == null) {
                        return true;
                    }
                }
            }
            Boolean result = handlerPlanTemplate(chapterTemplateList, chapterInstanceInfoMap, sysUser);
            if (result != null) {
                return result;
            }
        }

        // 验证模块是否一致
        Map<Long, ChapterInstance> chapterMap = chapterList.stream().collect(Collectors.toMap(item -> item.getTemplateId(), item -> item));
        for(PlanTemplateChapter templateChapter : chapterTemplateList) {
            ChapterInstance chapterInstance = chapterMap.get(templateChapter.getId());
            if (chapterInstance != null && chapterInstance.getIntroduceChapterId() == null) {
                // 关联模板的方案章节已删除，模块不再进行比对
                PlanModuleDelete planModule = new PlanModuleDelete();
                planModule.setPlanId(chapterInstance.getPlanId());
                planModule.setTemplateChapterId(chapterInstance.getTemplateId());
                PlanModuleDelete planModuleDelete = planModuleDeleteService.getPlanModuleDelete(planModule, sysUser);
                if (planModuleDelete != null) {
                    continue;
                }
                // 模板章节数据列表
                List<PlanTemplateChapterData> chapterDataList = planTemplateChapterService.findChapterDataList(templateChapter.getId());
                List<Long> chapterDataIdList = new ArrayList<>();
                Map<Long, PlanTemplateChapterData> templateChapterDataMap = new HashMap<>();
                if (!CollectionUtils.isEmpty(chapterDataList)) {
                    chapterDataIdList = chapterDataList.stream().map(chapterData -> chapterData.getId()).collect(Collectors.toList());
                    templateChapterDataMap = chapterDataList.stream().collect(Collectors.toMap(item -> item.getId(), item -> item));
                }

                // 章节数据列表
                ChapterContext chapterContext = chapterContextDao.getById(chapterInstance.getId());
                List<ContextModule> moduleList = chapterContext.getModuleList().stream().filter(module -> module.getIsFromTemplate()).collect(Collectors.toList());
                List<Long> chapterModuleIdList = moduleList.stream().map(module -> module.getId()).collect(Collectors.toList());
                Map<Long, ContextModule> chapterInstanceMap = moduleList.stream().collect(Collectors.toMap(item -> item.getId(), item -> item));

                // 校验模块是否一致
                if (!Objects.equals(chapterDataIdList.size(), chapterModuleIdList.size()) || !chapterDataIdList.containsAll(chapterModuleIdList)) {
                    // 判断有没有新增的模块
                    List<Long> templateData = new ArrayList<>(chapterDataIdList);
                    List<Long> planData = new ArrayList<>(chapterModuleIdList);
                    templateData.removeAll(planData);
                    if (!CollectionUtils.isEmpty(templateData)) {
                        for (Long chapterDataId : templateData) {
                            PlanTemplateChapterData chapterData = templateChapterDataMap.get(chapterDataId);
                            if (chapterData != null) {
                                List<PlanModuleDelete> planModuleDeleteList = planModuleDeleteService.findPlanModuleDeleteList(planId, null, chapterData.getId(), sysUser.getLoginCode());
                                if (CollectionUtils.isEmpty(planModuleDeleteList)) {
                                    return true;
                                }
                            }
                        }
                    }

                    if (chapterModuleIdList.size() > chapterDataIdList.size()) {
                        chapterModuleIdList.removeAll(chapterDataIdList);
                        if (!CollectionUtils.isEmpty(chapterModuleIdList)) {
                            for (Long chapterModuleId : chapterModuleIdList) {
                                ContextModule module = chapterInstanceMap.get(chapterModuleId);
                                if (module != null && !Objects.equals(module.getTemplateDelete(), 1)) {
                                    return true;
                                }
                            }
                        }
                    }

                    Boolean result = compareModuleOption(chapterDataList, chapterInstanceMap);
                    if (result != null) {
                        return result;
                    }
                } else {
                    Boolean result = compareModuleOption(chapterDataList, chapterInstanceMap);
                    if (result != null) {
                        return result;
                    }
                }
            }
        }
        return false;
    }

    @Override
    public Boolean checkAndQuietUpdate(Long planId) {
        Boolean result = checkPlanTemplate(planId);
        if (!result) {
            updatePlanTemplateQuiet(planId);
        }
        return result;
    }

    @Override
    public List<ChapterModuleVO> updatePlanTemplate(Long planId, SysUser sysUser) {
        if (planId == null) {
            throw new BusinessException("参数不能为空!");
        }
        UserInfo userInfo = null;
        try {
            userInfo = userApiSvc.getUserInfoByLoginCode(sysUser.getLoginCode());
        } catch (Exception e) {
            throw new BusinessException("当前用户已被删除!");
        }

        if (userInfo == null) {
            throw new BusinessException("当前用户已被删除!");
        }

        PlanDesignInstance plan = planDesignInstanceDao.getById(planId);
        if (plan == null) {
            throw new BusinessException("获取方案信息异常!");
        }
        DlvrTemplateVO dlvrTemplate = deliverableTemplateService.getDlvrTemplateById(plan.getTemplateId());
        if (dlvrTemplate == null || !Objects.equals(dlvrTemplate.getStatus(), 3)) {
            throw new BusinessException("方案模板不能使用!");
        }
        plan.setTemplateVersion(dlvrTemplate.getTemplateVersion());
        planDesignInstanceDao.saveOrUpdate(plan);
        // 返回模块内容
        List<ChapterModuleVO> chapterModuleList = new ArrayList<>();

        // 获取方案章节列表
        BoolQueryBuilder query = QueryBuilders.boolQuery();
        query.must(QueryBuilders.termQuery("planId", planId));
        query.must(QueryBuilders.termQuery("isFromTemplate", true));
        query.must(QueryBuilders.termQuery("deleted", false));
        List<SortBuilder<?>> sorts = new ArrayList<>();
        SortBuilder<?> levelSort = SortBuilders.fieldSort("level").order(SortOrder.ASC);
        SortBuilder<?> timeSort = SortBuilders.fieldSort("serialNum.keyword").order(SortOrder.ASC);
        sorts.add(levelSort);
        sorts.add(timeSort);
        long count = planChapterInstanceDao.countByCondition(query);
        Page<ChapterInstance> chapterPage = planChapterInstanceDao.getSortListByQuery(1, (int)count, query, sorts);
        List<ChapterInstance> chapterList = chapterPage.getData();
        List<Long> chapterIdList = chapterList.stream().map(chapter -> chapter.getTemplateId()).collect(Collectors.toList());
        Map<Long, ChapterInstance> chapterInstanceMap = chapterList.stream().collect(Collectors.toMap(item -> item.getTemplateId(), item -> item));

        // 获取方案模板章节数据
        List<PlanTemplateChapter> chapterTemplateList = planTemplateChapterService.findPlanChapterList(plan.getTemplateId());
        for (PlanTemplateChapter planTemplateChapter : chapterTemplateList) {
            chapterIdList.remove(planTemplateChapter.getId());

            // 对比方案中的模板章节和模板章节
            ChapterInstance chapterInstance = chapterInstanceMap.get(planTemplateChapter.getId());
            if (chapterInstance != null) {
                // 关联模板的方案章节已删除，模块不再进行比对
                PlanModuleDelete planModule = new PlanModuleDelete();
                planModule.setPlanId(chapterInstance.getPlanId());
                planModule.setTemplateChapterId(chapterInstance.getTemplateId());
                PlanModuleDelete planModuleDelete = planModuleDeleteService.getPlanModuleDelete(planModule, sysUser);
                if (planModuleDelete != null) {
                    continue;
                }
                if (chapterInstance.getTemplateParentId() != null && (!Objects.equals(planTemplateChapter.getParentId(), chapterInstance.getTemplateParentId())
                        || !Objects.equals(planTemplateChapter.getLevel(), chapterInstance.getLevel()))) {
                    Long oldTemplateId = chapterInstance.getTemplateId();
                    Long oldTemplateParentId = chapterInstance.getTemplateParentId();
                    Integer oldLevel = chapterInstance.getLevel();
                    // 模板存在章节，方案中不存在，方案新增章节，并控制方案中的顺序
                    chapterInstance = handlePlanAddChapter(plan, planTemplateChapter, chapterInstanceMap, userInfo, chapterModuleList);
                    if (chapterInstance == null) {
                        continue;
                    }

                    // 删除关联删除废弃的模板
                    BoolQueryBuilder deleteQuery = QueryBuilders.boolQuery();
                    deleteQuery.must(QueryBuilders.termQuery("planId", chapterInstance.getPlanId()));
                    deleteQuery.must(QueryBuilders.termQuery("templateId", oldTemplateId));
                    deleteQuery.must(QueryBuilders.termQuery("templateParentId", oldTemplateParentId));
                    deleteQuery.must(QueryBuilders.termQuery("level", oldLevel));
                    List<ChapterInstance> chapterInstanceList = planChapterInstanceDao.getListByQuery(deleteQuery);
                    if (!CollectionUtils.isEmpty(chapterInstanceList)) {
                        planChapterInstanceDao.deleteByQuery(deleteQuery, true);
                        Set<Long> moduleIds = chapterInstanceList.stream().map(chapter -> chapter.getId()).collect(Collectors.toSet());
                        chapterContextDao.deleteByIds(moduleIds);
                    }
                } else {
                    // 方案和模板都存在章节，就对比章节各个选项
                    contrastChapterOption(planTemplateChapter, chapterInstance, chapterModuleList);
                }
            } else {
                // 模板存在章节，方案中不存在，方案新增章节，并控制方案中的顺序
                chapterInstance = handlePlanAddChapter(plan, planTemplateChapter, chapterInstanceMap, userInfo, chapterModuleList);
                if (chapterInstance == null) {
                    continue;
                }
            }

            // 方案章节模块和模板章节模块对比
            contrastChapterModule(planId, chapterInstance, planTemplateChapter, chapterModuleList, sysUser);
        }
        // 处理方案中被删除的章节
        handleDeleteChapter(chapterIdList, chapterInstanceMap, chapterModuleList);
        return chapterModuleList;
    }

    /**
     * 静默更新 nameOnlyEditDisplay（内容块名称是否仅在编辑模式下显示）
     * @param planId
     * @return
     */
    public void updatePlanTemplateQuiet(Long planId) {
        if (planId == null) {
            log.error("updatePlanTemplateQuiet planId为空");
            return;
        }
        PlanDesignInstance plan = planDesignInstanceDao.getById(planId);
        if (plan == null) {
            log.error("updatePlanTemplateQuiet 获取方案信息异常为空，planId：{}", planId);
            return;
        }
        if (PlanStatusEnum.deleted.name().equals(plan.getStatus())
                || PlanStatusEnum.published.name().equals(plan.getStatus())
                || PlanStatusEnum.history.name().equals(plan.getStatus())) {
            log.info("删除/发布/历史版本,无需静默更新，planId:{}", planId);
            return;
        }
        DlvrTemplateVO dlvrTemplate = deliverableTemplateService.getDlvrTemplateById(plan.getTemplateId());
        if (dlvrTemplate == null || !Objects.equals(dlvrTemplate.getStatus(), 3)) {
            log.error("updatePlanTemplateQuiet 方案模板不能使用");
            return;
        }

        // 获取方案章节列表
        BoolQueryBuilder query = QueryBuilders.boolQuery();
        query.must(QueryBuilders.termQuery("planId", planId));
        query.must(QueryBuilders.termQuery("isFromTemplate", true));
        query.must(QueryBuilders.termQuery("deleted", false));
        List<SortBuilder<?>> sorts = new ArrayList<>();
        SortBuilder<?> levelSort = SortBuilders.fieldSort("level").order(SortOrder.ASC);
        SortBuilder<?> timeSort = SortBuilders.fieldSort("serialNum.keyword").order(SortOrder.ASC);
        sorts.add(levelSort);
        sorts.add(timeSort);
        long count = planChapterInstanceDao.countByCondition(query);
        Page<ChapterInstance> chapterPage = planChapterInstanceDao.getSortListByQuery(1, (int)count, query, sorts);
        List<ChapterInstance> chapterList = chapterPage.getData();
        Map<Long, ChapterInstance> chapterInstanceMap = chapterList.stream().collect(Collectors.toMap(item -> item.getTemplateId(), item -> item));

        // 获取方案模板章节数据
        List<PlanTemplateChapter> chapterTemplateList = planTemplateChapterService.findPlanChapterList(plan.getTemplateId());
        for (PlanTemplateChapter planTemplateChapter : chapterTemplateList) {

            // 根据模板中的 nameOnlyEditDisplay 字段更新到方案模块中
            ChapterInstance chapterInstance = chapterInstanceMap.get(planTemplateChapter.getId());
            if (chapterInstance != null) {
                handleNameDisplay(chapterInstance, planTemplateChapter);
            }
        }

    }

    /**
     * 根据模板中的 nameOnlyEditDisplay 字段更新到方案模块中
     * @param chapterInstance 方案的章节信息
     * @param planTemplateChapter 模板的章节信息
     */
    private void handleNameDisplay(ChapterInstance chapterInstance, PlanTemplateChapter planTemplateChapter) {
        if (chapterInstance.getIntroduceChapterId() == null) {
            // 模板的模块信息
            List<PlanTemplateChapterData> chapterDataList = planTemplateChapterService.findChapterDataList(planTemplateChapter.getId());
            Map<Long, PlanTemplateChapterData> templateChapterDataMap = chapterDataList.stream().collect(Collectors.toMap(item -> item.getId(), item -> item));

            // 方案的模块信息
            ChapterContext chapterContext = chapterContextDao.getById(chapterInstance.getId());
            if (chapterContext != null) {
                List<ContextModule> moduleList = chapterContext.getModuleList();

                for (ContextModule module : moduleList) {
                    PlanTemplateChapterData templateChapterData = templateChapterDataMap.get(module.getId());
                    if (templateChapterData != null) {
                        module.getModuleDefinition().setNameOnlyEditDisplay(templateChapterData.getNameOnlyEditDisplay());
                    }
                }
                chapterContextDao.saveOrUpdate(chapterContext);
            }
        }
    }

    @Override
    public void deletePlanChapter(Long id) {
        if (id == null) {
            return;
        }
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(QueryBuilders.termQuery("planId", id));
        planChapterInstanceDao.deleteByQuery(boolQueryBuilder, true);
    }

    /**
     * 方案和模板都存在章节，就对比章节各个选项
     * @param planTemplateChapter
     * @param chapterInstance
     * @param chapterModuleList
     */
    private void contrastChapterOption(PlanTemplateChapter planTemplateChapter, ChapterInstance chapterInstance, List<ChapterModuleVO> chapterModuleList) {
        boolean result = false;

        boolean resourceResult = false;
        List<ChapterResource> planResource = cjResourceDaoService.getPlanResource(planTemplateChapter.getPlanTemplateId(), planTemplateChapter.getId());
        if ((CollectionUtils.isEmpty(planResource) && !CollectionUtils.isEmpty(chapterInstance.getChapterResources()))
                || (!CollectionUtils.isEmpty(planResource) && CollectionUtils.isEmpty(chapterInstance.getChapterResources()))) {
            resourceResult = true;
        }
        if (!CollectionUtils.isEmpty(planResource) && !CollectionUtils.isEmpty(chapterInstance.getChapterResources())) {
            if (!Objects.equals(planResource.size(), chapterInstance.getChapterResources().size())) {
                resourceResult = true;
            } else {
                List<Long> templateResource = planResource.stream().map(resource -> resource.getId()).collect(Collectors.toList());
                List<Long> planResourceInfo = chapterInstance.getChapterResources().stream().map(resource -> resource.getId()).collect(Collectors.toList());
                if (!templateResource.containsAll(planResourceInfo)) {
                    resourceResult = true;
                }
            }
        }

        boolean introduceResult = false;
        List<PlanTemplateIntroduceChapterVo> templateIntroduceList = planTemplateChapter.getPlanTemplateIntroduceChapterVoList();
        List<PlanTemplateIntroduceChapterVo> planIntroduceList = chapterInstance.getPlanTemplateIntroduceChapterVoList();
        if ((CollectionUtils.isEmpty(templateIntroduceList) && !CollectionUtils.isEmpty(planIntroduceList))
                || (!CollectionUtils.isEmpty(templateIntroduceList) && CollectionUtils.isEmpty(planIntroduceList))) {
            introduceResult = true;
        }
        if (!CollectionUtils.isEmpty(templateIntroduceList) && !CollectionUtils.isEmpty(planIntroduceList)) {
            if (!Objects.equals(templateIntroduceList.size(), planIntroduceList.size())) {
                introduceResult = true;
            } else {
                List<Long> templateIntroduce = templateIntroduceList.stream().map(resource -> resource.getPlanTemplateChapterId()).collect(Collectors.toList());
                List<Long> planIntroduce = planIntroduceList.stream().map(resource -> resource.getPlanTemplateChapterId()).collect(Collectors.toList());
                if (!templateIntroduce.containsAll(planIntroduce)) {
                    introduceResult = true;
                }
            }
        }

        ChapterContext context = chapterContextDao.getById(chapterInstance.getId());
        String required = chapterInstance.getRequired() ? "1" : "0";
        String userAddContent = context.getUserAddContent() ? "1" : "0";
        //用户自己改过方案章节名称，模板章节名称发生修改时，不需要再更新方案章节名称
        boolean modifyNameByUser = Constants.CHAPTER_NAME_UPDATE_BY_USER.equals(chapterInstance.getModifyNameType());
        boolean templateUpdateName = !modifyNameByUser && !Objects.equals(chapterInstance.getName(), planTemplateChapter.getChapterName());
        boolean chapterResult = templateUpdateName || !Objects.equals(required, planTemplateChapter.getRequired()) || resourceResult || introduceResult;
        if (chapterResult) {
            if (templateUpdateName) {
                chapterInstance.setName(planTemplateChapter.getChapterName());
                chapterInstance.setModifyNameType(Constants.CHAPTER_NAME_UPDATE_BY_TEMPLATE);
            }
            boolean content = Objects.equals(planTemplateChapter.getRequired(), "1");
            chapterInstance.setRequired(content);
            chapterInstance.setChapterResources(planResource);
            chapterInstance.setPlanTemplateIntroduceChapterVoList(templateIntroduceList);
            planChapterInstanceDao.saveOrUpdate(chapterInstance);
            result = true;
        }

        boolean contextResult = !Objects.equals(context.getChapterDesc(), planTemplateChapter.getChapterDesc()) || !Objects.equals(userAddContent, planTemplateChapter.getUserAddContent())
                || !Objects.equals(context.getRemark(), planTemplateChapter.getRemarkInfo());
        if (contextResult) {
            context.setChapterDesc(planTemplateChapter.getChapterDesc());
            boolean content = Objects.equals(planTemplateChapter.getUserAddContent(), "1");
            context.setUserAddContent(content);
            context.setRemark(planTemplateChapter.getRemarkInfo());
            chapterContextDao.saveOrUpdate(context);
            result = true;
        }

        if (result) {
            // 添加章节新增标识
            /*ChapterModuleVO chapterModuleVO = new ChapterModuleVO();
            chapterModuleVO.setChapterId(chapterInstance.getId());
            chapterModuleVO.setSign(2);
            chapterModuleList.add(chapterModuleVO);*/
            handleChapterModule(chapterModuleList, chapterInstance.getId(), null, Constants.UPDATE_SIGN, null, false);
        }
    }

    /**
     * 模板存在章节，方案中不存在，方案新增章节，并控制方案中的顺序
     * @param plan
     * @param planTemplateChapter
     * @param chapterInstanceMap
     * @param userInfo
     * @param chapterModuleList
     * @return
     */
    private ChapterInstance handlePlanAddChapter(PlanDesignInstance plan, PlanTemplateChapter planTemplateChapter, Map<Long, ChapterInstance> chapterInstanceMap,
                                      UserInfo userInfo, List<ChapterModuleVO> chapterModuleList) {
        // 判断用户是否已删掉关联模板的章节，已删掉不在新增
        List<Long> collect = Stream.of(planTemplateChapter.getId()).collect(Collectors.toList());
        List<PlanModuleDelete> planModuleDeleteList = planModuleDeleteService.findPlanModuleDeleteList(plan.getId(), collect, null, userInfo.getLoginCode());
        if (!CollectionUtils.isEmpty(planModuleDeleteList)) {
            return null;
        }

        Long templateParentId = planTemplateChapter.getParentId();
        // 判断位置
        List<PlanTemplateChapter> levelChapterList = planTemplateChapterService.findLevelTemplateChapterList(plan.getTemplateId(), templateParentId, planTemplateChapter.getLevel());
        List<Long> levelChapterIdList = levelChapterList.stream().map(chapter -> chapter.getId()).collect(Collectors.toList());
        int i = levelChapterIdList.indexOf(planTemplateChapter.getId());

        int deleteNum = 0;
        List<PlanModuleDelete> levelModuleDeleteList = planModuleDeleteService.findPlanModuleDeleteList(plan.getId(), levelChapterIdList, null, userInfo.getLoginCode());
        if (!CollectionUtils.isEmpty(levelModuleDeleteList)) {
            for (PlanModuleDelete moduleDelete : levelModuleDeleteList) {
                Long templateChapterId = moduleDelete.getTemplateChapterId();
                int deleteModuleIndex = levelChapterIdList.indexOf(templateChapterId);
                if (i > deleteModuleIndex) {
                    deleteNum = ++deleteNum;
                }
            }
        }

        ChapterInstance addChapterInstance = new ChapterInstance();
        int num = i - deleteNum + 1;
        if (templateParentId == 0) {
            addChapterInstance.setParentId(0L);
            addChapterInstance.setSerialNum(String.format("%s", num));
        } else {
            ChapterInstance parentChapter = chapterInstanceMap.get(templateParentId);
            if (parentChapter == null) {
                return null;
            }
            addChapterInstance.setParentId(parentChapter.getId());
            addChapterInstance.setSerialNum(String.format("%s.%s", parentChapter.getSerialNum(), num));
        }
        addChapterInstance.setPlanId(plan.getId());
        setOrderIdAndLevel(addChapterInstance);
        addChapterInstance.setOrderId((double)num);
        addChapterInstance.setName(planTemplateChapter.getChapterName());
        addChapterInstance.setIsFromTemplate(true);
        boolean required = Objects.equals(planTemplateChapter.getRequired(), "1");
        addChapterInstance.setRequired(required);
        addChapterInstance.setExpand(true);
        addChapterInstance.setDeleted(false);
        addChapterInstance.setId(ESUtil.getUUID());
        addChapterInstance.setCreatorName(userInfo.getUserName());
        addChapterInstance.setCreateTime(ESUtil.getNumberDateTime());
        addChapterInstance.setModifierCode(userInfo.getLoginCode());
        addChapterInstance.setModifyTime(ESUtil.getNumberDateTime());
        addChapterInstance.setModifierName(userInfo.getUserName());
        addChapterInstance.setDomainId(userInfo.getDomainId());
        addChapterInstance.setTemplateId(planTemplateChapter.getId());
        List<ChapterResource> planResource = cjResourceDaoService.getPlanResource(planTemplateChapter.getPlanTemplateId(), planTemplateChapter.getId());
        addChapterInstance.setChapterResources(planResource);
        List<PlanTemplateIntroduceChapterVo> templateIntroduceList = planTemplateChapter.getPlanTemplateIntroduceChapterVoList();
        addChapterInstance.setPlanTemplateIntroduceChapterVoList(templateIntroduceList);
        addChapterInstance.setBusinessId(String.valueOf(ESUtil.getUUID()));
        addChapterInstance.setVersion(String.valueOf(ESUtil.getUUID()));
        addChapterInstance.setStatus(Constants.DRAFT);
        addChapterInstance.setTemplateParentId(planTemplateChapter.getParentId());
        planChapterInstanceDao.saveOrUpdate(addChapterInstance);

        // 修改方案章节顺序
        BoolQueryBuilder levelQuery = QueryBuilders.boolQuery();
        levelQuery.must(QueryBuilders.termQuery("planId", plan.getId()));
        levelQuery.must(QueryBuilders.termQuery("parentId", addChapterInstance.getParentId()));
        levelQuery.must(QueryBuilders.termQuery("level", addChapterInstance.getLevel()));
        levelQuery.must(QueryBuilders.termQuery("deleted", false));
        List<ChapterInstance> chapterInstanceList = planChapterInstanceDao.getListByQuery(levelQuery);
        List<ChapterInstance> serialList = new ArrayList<>();
        for (ChapterInstance instance : chapterInstanceList) {
            String serialNum = instance.getSerialNum();
            Double orderId = instance.getOrderId();
            if (Objects.equals(addChapterInstance.getLevel(), 1)) {
                Integer value = Integer.valueOf(serialNum);
                Integer newOrderId = value;
                if (value >= num && !Objects.equals(instance.getId(), addChapterInstance.getId())) {
                    instance.setSerialNum(String.valueOf(++value));
                    instance.setOrderId(Double.valueOf(++newOrderId));
                    //instance.setOrderId(++orderId);
                    serialList.add(instance);
                    chapterInstanceMap.put(instance.getTemplateId(), instance);
                }
            } else {
                String[] split = serialNum.split("\\.");
                Integer value = Integer.valueOf(split[addChapterInstance.getLevel() - 1]);
                if (value >= num && !Objects.equals(instance.getId(), addChapterInstance.getId())) {
                    String substring = serialNum.substring(0, serialNum.length() - 1);
                    instance.setSerialNum(substring + String.valueOf(++value));
                    instance.setOrderId(++orderId);
                    serialList.add(instance);
                    chapterInstanceMap.put(instance.getTemplateId(), instance);
                }
            }

        }
        planChapterInstanceDao.saveOrUpdateBatch(serialList);
        // 处理子章节排序
        List<ChapterInstance> childChapterInstance = new ArrayList<>();
        for (ChapterInstance chapter : serialList) {
            handleChildSerialNum(chapter, childChapterInstance);
        }
        planChapterInstanceDao.saveOrUpdateBatch(childChapterInstance);

        chapterInstanceMap.put(planTemplateChapter.getId(), addChapterInstance);

        // 添加章节新增标识
        /*ChapterModuleVO chapterModuleVO = new ChapterModuleVO();
        chapterModuleVO.setChapterId(addChapterInstance.getId());
        chapterModuleVO.setSign(1);
        chapterModuleList.add(chapterModuleVO);*/
        handleChapterModule(chapterModuleList, addChapterInstance.getId(), null, Constants.ADD_SIGN, null, false);
        return addChapterInstance;
    }

    /**
     * 方案章节模块和模板章节模块对比
     * @param planId
     * @param chapterInstance
     * @param planTemplateChapter
     * @param chapterModuleList
     */
    private void contrastChapterModule(Long planId, ChapterInstance chapterInstance, PlanTemplateChapter planTemplateChapter, List<ChapterModuleVO> chapterModuleList, SysUser sysUser) {
        if (chapterInstance.getIntroduceChapterId() == null) {
            // 对比章节中的模块
            List<PlanTemplateChapterData> chapterDataList = planTemplateChapterService.findChapterDataList(planTemplateChapter.getId());
            List<Long> chapterDataIdList = chapterDataList.stream().map(chapterData -> chapterData.getId()).collect(Collectors.toList());

            ChapterContext chapterContext = chapterContextDao.getById(chapterInstance.getId());
            if (chapterContext != null) {
                List<ContextModule> moduleList = chapterContext.getModuleList();
                List<Long> chapterModuleIdList = moduleList.stream().map(module -> module.getId()).collect(Collectors.toList());
                Map<Long, ContextModule> contextModuleMap = moduleList.stream().collect(Collectors.toMap(item -> item.getId(), item -> item));

                List<ContextModule> newContextModule = new ArrayList<>();
                if (!Objects.equals(chapterDataIdList.size(), chapterModuleIdList.size()) || !chapterDataIdList.containsAll(chapterModuleIdList)) {
                    for (PlanTemplateChapterData chapterData : chapterDataList) {
                        ContextModule module = contextModuleMap.get(chapterData.getId());
                        // 判断模块是否已经删除过
                        List<PlanModuleDelete> planModuleDeleteList = planModuleDeleteService.findPlanModuleDeleteList(planId, null, chapterData.getId(), sysUser.getLoginCode());
                        if (module == null) {
                            if (CollectionUtils.isEmpty(planModuleDeleteList)) {
                                module = new ContextModule();
                                module.setIsFromTemplate(true);
                                module.setId(chapterData.getId());
                                module.setModuleDefinition(chapterData);
                                if (Objects.equals(chapterData.getType(), ChapterDataTypeEnum.RICH_TEXT.getDataType()) && !StringUtils.isEmpty(chapterData.getInitRichText())) {
                                    JSONObject jsonObject = new JSONObject();
                                    jsonObject.put("data", chapterData.getInitRichText());
                                    module.setData(jsonObject.toJSONString());
                                } else {
                                    String data = "{}";
                                    module.setData(data);
                                }

                                // 处理模块是删除/新增/修改
                                handleChapterModule(chapterModuleList, chapterInstance.getId(), chapterData.getId(), Constants.UPDATE_SIGN, Constants.ADD_SIGN, true);
                            }
                        }else{
                            // 比对章节模块选项数据
                            handleModuleOption(chapterModuleList, chapterInstance, chapterData, module);
                        }
                        // 章节模块列表移除
                        chapterModuleIdList.remove(chapterData.getId());
                        if (module != null) {
                            newContextModule.add(module);
                        }
                    }

                    for (Long moduleId : chapterModuleIdList) {
                        ContextModule module = contextModuleMap.get(moduleId);
                        if (module != null) {
                            if (!Objects.equals(module.getTemplateDelete(), 1)) {
                                module.setTemplateDelete(1);
                                newContextModule.add(module);
                                // 处理模块是删除/新增/修改
                                handleChapterModule(chapterModuleList, chapterInstance.getId(), moduleId, Constants.UPDATE_SIGN, Constants.DELETE_SIGN, true);
                            } else {
                                newContextModule.add(module);
                            }
                        }
                    }
                    chapterContext.setModuleList(newContextModule);
                    chapterContextDao.saveOrUpdate(chapterContext);
                } else {
                    for (PlanTemplateChapterData chapterData : chapterDataList) {
                        ContextModule module = contextModuleMap.get(chapterData.getId());
                        // 比对章节模块选项数据
                        handleModuleOption(chapterModuleList, chapterInstance, chapterData, module);
                        newContextModule.add(module);
                    }
                    chapterContext.setModuleList(newContextModule);
                    chapterContextDao.saveOrUpdate(chapterContext);
                }

            } else {
                chapterContext = new ChapterContext();
                chapterContext.setId(chapterInstance.getId());
                chapterContext.setPlanId(planId);
                boolean content = Objects.equals(planTemplateChapter.getUserAddContent(), "1");
                chapterContext.setUserAddContent(content);
                chapterContext.setBusinessId(String.valueOf(ESUtil.getUUID()));
                chapterContext.setStatus(1);
                chapterContext.setRemark(planTemplateChapter.getRemarkInfo());
                chapterContext.setChapterDesc(planTemplateChapter.getChapterDesc());
                List<ContextModule> newContextModule = new ArrayList<>();
                for (PlanTemplateChapterData chapterData : chapterDataList) {
                    // 判断模块是否已经删除过
                    List<PlanModuleDelete> planModuleDeleteList = planModuleDeleteService.findPlanModuleDeleteList(planId, null, chapterData.getId(), sysUser.getLoginCode());
                    if (CollectionUtils.isEmpty(planModuleDeleteList)) {
                        ContextModule module = new ContextModule();
                        module.setIsFromTemplate(true);
                        module.setId(chapterData.getId());
                        module.setModuleDefinition(chapterData);
                        if (Objects.equals(chapterData.getType(), ChapterDataTypeEnum.RICH_TEXT.getDataType()) && !StringUtils.isEmpty(chapterData.getInitRichText())) {
                            JSONObject jsonObject = new JSONObject();
                            jsonObject.put("data", chapterData.getInitRichText());
                            module.setData(jsonObject.toJSONString());
                        } else {
                            String data = "{}";
                            module.setData(data);
                        }
                        newContextModule.add(module);

                        // 处理模块是删除/新增/修改
                        handleChapterModule(chapterModuleList, chapterInstance.getId(), chapterData.getId(), Constants.UPDATE_SIGN, Constants.ADD_SIGN, true);
                    }
                }
                chapterContext.setModuleList(newContextModule);
                chapterContextDao.saveOrUpdate(chapterContext);
            }
        }
    }

    /**
     * 比对章节模块选项数据
     * @param chapterModuleList
     * @param chapterInstance
     * @param chapterData
     * @param module
     */
    private void handleModuleOption(List<ChapterModuleVO> chapterModuleList, ChapterInstance chapterInstance, PlanTemplateChapterData chapterData, ContextModule module) {
        PlanTemplateChapterData moduleDefinition = module.getModuleDefinition();
        Integer type = module.getModuleDefinition().getType();
        //TODO 对比模板章节内容块和方案章节内容块富文本
        if (Objects.equals(type, ChapterDataTypeEnum.RICH_TEXT.getDataType())) {
            ValidateTextChange(chapterData,module,chapterInstance,chapterModuleList);
        } else if (Objects.equals(type, ChapterDataTypeEnum.APPENDIX.getDataType())) {
            //TODO 处理模板内容块与方案内容块富文本变更
            ValidateAttachmentChange(chapterData,module,chapterInstance,chapterModuleList);
        } else if (Objects.equals(type, ChapterDataTypeEnum.PRODUCT.getDataType())) {
            if (!Objects.equals(chapterData.getProductName(), moduleDefinition.getProductName())) {
                moduleDefinition.setProductName(chapterData.getProductName());
                handleChapterModule(chapterModuleList, chapterInstance.getId(), chapterData.getId(), Constants.UPDATE_SIGN, Constants.UPDATE_SIGN, true);
            }
            if (!Objects.equals(chapterData.getProductRequired(), moduleDefinition.getProductRequired())) {
                moduleDefinition.setProductRequired(chapterData.getProductRequired());
                handleChapterModule(chapterModuleList, chapterInstance.getId(), chapterData.getId(), Constants.UPDATE_SIGN, Constants.UPDATE_SIGN, true);
            }
            if (!Objects.equals(chapterData.getProductControl(), moduleDefinition.getProductControl())) {
                moduleDefinition.setProductControl(chapterData.getProductControl());
                handleChapterModule(chapterModuleList, chapterInstance.getId(), chapterData.getId(), Constants.UPDATE_SIGN, Constants.UPDATE_SIGN, true);
            }
            /*if (!Objects.equals(chapterData.getProductType(), moduleDefinition.getProductType())) {
                moduleDefinition.setProductType(chapterData.getProductType());
                handleChapterModule(chapterModuleList, chapterInstance.getId(), chapterData.getId(), Constants.UPDATE_SIGN, Constants.UPDATE_SIGN, true);
            }*/
            if (!Objects.equals(chapterData.getDiagramProductType(), moduleDefinition.getDiagramProductType())) {
                moduleDefinition.setDiagramProductType(chapterData.getDiagramProductType());
                handleChapterModule(chapterModuleList, chapterInstance.getId(), chapterData.getId(), Constants.UPDATE_SIGN, Constants.UPDATE_SIGN, true);
            }
            if ((chapterData.getReferencesInfo() != null && module.getModuleDefinition().getReferencesInfo() == null)
                    || (chapterData.getReferencesInfo() == null && module.getModuleDefinition().getReferencesInfo() != null)
                    || (chapterData.getReferencesInfo() != null && module.getModuleDefinition().getReferencesInfo() != null
                    && (!Objects.equals(chapterData.getReferencesInfo().getReferencesClassCode(), module.getModuleDefinition().getReferencesInfo().getReferencesClassCode())
                    || (CollectionUtils.isEmpty(chapterData.getReferencesInfo().getReferencesCiCodes()) && !CollectionUtils.isEmpty(module.getModuleDefinition().getReferencesInfo().getReferencesCiCodes()))
                    || (!CollectionUtils.isEmpty(chapterData.getReferencesInfo().getReferencesCiCodes()) && CollectionUtils.isEmpty(module.getModuleDefinition().getReferencesInfo().getReferencesCiCodes()))
                    || (!CollectionUtils.isEmpty(chapterData.getReferencesInfo().getReferencesCiCodes()) && !CollectionUtils.isEmpty(module.getModuleDefinition().getReferencesInfo().getReferencesCiCodes())
                    && (!Objects.equals(chapterData.getReferencesInfo().getReferencesCiCodes().size(), module.getModuleDefinition().getReferencesInfo().getReferencesCiCodes().size())
                    || !chapterData.getReferencesInfo().getReferencesCiCodes().containsAll(module.getModuleDefinition().getReferencesInfo().getReferencesCiCodes())))))) {
                module.getModuleDefinition().setReferencesInfo(chapterData.getReferencesInfo());
                handleChapterModule(chapterModuleList, chapterInstance.getId(), chapterData.getId(), Constants.UPDATE_SIGN, Constants.UPDATE_SIGN, true);
            }
        } else if (Objects.equals(type, ChapterDataTypeEnum.DATA_SET.getDataType())) {
            if (!Objects.equals(chapterData.getDataSetName(), moduleDefinition.getDataSetName())) {
                moduleDefinition.setDataSetName(chapterData.getDataSetName());
                handleChapterModule(chapterModuleList, chapterInstance.getId(), chapterData.getId(), Constants.UPDATE_SIGN, Constants.UPDATE_SIGN, true);
            }
            if (!Objects.equals(chapterData.getDataSetRequired(), moduleDefinition.getDataSetRequired())) {
                moduleDefinition.setDataSetRequired(chapterData.getDataSetRequired());
                handleChapterModule(chapterModuleList, chapterInstance.getId(), chapterData.getId(), Constants.UPDATE_SIGN, Constants.UPDATE_SIGN, true);
            }
            if (!Objects.equals(chapterData.getDataSetId(), moduleDefinition.getDataSetId())) {
                moduleDefinition.setDataSetId(chapterData.getDataSetId());
                handleChapterModule(chapterModuleList, chapterInstance.getId(), chapterData.getId(), Constants.UPDATE_SIGN, Constants.UPDATE_SIGN, true);
            }
            if ((chapterData.getReferencesInfo() != null && module.getModuleDefinition().getReferencesInfo() == null)
                    || (chapterData.getReferencesInfo() == null && module.getModuleDefinition().getReferencesInfo() != null)
                    || (chapterData.getReferencesInfo() != null && module.getModuleDefinition().getReferencesInfo() != null
                    && (!Objects.equals(chapterData.getReferencesInfo().getReferencesClassCode(), module.getModuleDefinition().getReferencesInfo().getReferencesClassCode())
                    || (CollectionUtils.isEmpty(chapterData.getReferencesInfo().getReferencesCiCodes()) && !CollectionUtils.isEmpty(module.getModuleDefinition().getReferencesInfo().getReferencesCiCodes()))
                    || (!CollectionUtils.isEmpty(chapterData.getReferencesInfo().getReferencesCiCodes()) && CollectionUtils.isEmpty(module.getModuleDefinition().getReferencesInfo().getReferencesCiCodes()))
                    || (!CollectionUtils.isEmpty(chapterData.getReferencesInfo().getReferencesCiCodes()) && !CollectionUtils.isEmpty(module.getModuleDefinition().getReferencesInfo().getReferencesCiCodes())
                    && (!Objects.equals(chapterData.getReferencesInfo().getReferencesCiCodes().size(), module.getModuleDefinition().getReferencesInfo().getReferencesCiCodes().size())
                    || !chapterData.getReferencesInfo().getReferencesCiCodes().containsAll(module.getModuleDefinition().getReferencesInfo().getReferencesCiCodes())))))) {
                module.getModuleDefinition().setReferencesInfo(chapterData.getReferencesInfo());
                handleChapterModule(chapterModuleList, chapterInstance.getId(), chapterData.getId(), Constants.UPDATE_SIGN, Constants.UPDATE_SIGN, true);
            }
        } else if (Objects.equals(type, ChapterDataTypeEnum.DATA_TABLE.getDataType())) {
            if (!Objects.equals(chapterData.getDataTableName(), moduleDefinition.getDataTableName())) {
                moduleDefinition.setDataTableName(chapterData.getDataTableName());
                handleChapterModule(chapterModuleList, chapterInstance.getId(), chapterData.getId(), Constants.UPDATE_SIGN, Constants.UPDATE_SIGN, true);
            }
            if (!Objects.equals(chapterData.getDataTableRequired(), moduleDefinition.getDataTableRequired())) {
                moduleDefinition.setDataTableRequired(chapterData.getDataTableRequired());
                handleChapterModule(chapterModuleList, chapterInstance.getId(), chapterData.getId(), Constants.UPDATE_SIGN, Constants.UPDATE_SIGN, true);
            }
            if (!Objects.equals(chapterData.getUserAddRow(), moduleDefinition.getUserAddRow())) {
                moduleDefinition.setUserAddRow(chapterData.getUserAddRow());
                handleChapterModule(chapterModuleList, chapterInstance.getId(), chapterData.getId(), Constants.UPDATE_SIGN, Constants.UPDATE_SIGN, true);
            }
            if (!Objects.equals(chapterData.getDataTableRemarkStatus(), moduleDefinition.getDataTableRemarkStatus())) {
                moduleDefinition.setDataTableRemarkStatus(chapterData.getDataTableRemarkStatus());
                handleChapterModule(chapterModuleList, chapterInstance.getId(), chapterData.getId(), Constants.UPDATE_SIGN, Constants.UPDATE_SIGN, true);
            }
            if (!Objects.equals(chapterData.getDataTableRemarkInfo(), moduleDefinition.getDataTableRemarkInfo())) {
                moduleDefinition.setDataTableRemarkInfo(chapterData.getDataTableRemarkInfo());
                handleChapterModule(chapterModuleList, chapterInstance.getId(), chapterData.getId(), Constants.UPDATE_SIGN, Constants.UPDATE_SIGN, true);
            }
            if ((chapterData.getReferencesInfo() != null && module.getModuleDefinition().getReferencesInfo() == null)
                    || (chapterData.getReferencesInfo() == null && module.getModuleDefinition().getReferencesInfo() != null)
                    || (chapterData.getReferencesInfo() != null && module.getModuleDefinition().getReferencesInfo() != null
                    && (!Objects.equals(chapterData.getReferencesInfo().getReferencesClassCode(), module.getModuleDefinition().getReferencesInfo().getReferencesClassCode())
                    || (CollectionUtils.isEmpty(chapterData.getReferencesInfo().getReferencesCiCodes()) && !CollectionUtils.isEmpty(module.getModuleDefinition().getReferencesInfo().getReferencesCiCodes()))
                    || (!CollectionUtils.isEmpty(chapterData.getReferencesInfo().getReferencesCiCodes()) && CollectionUtils.isEmpty(module.getModuleDefinition().getReferencesInfo().getReferencesCiCodes()))
                    || (!CollectionUtils.isEmpty(chapterData.getReferencesInfo().getReferencesCiCodes()) && !CollectionUtils.isEmpty(module.getModuleDefinition().getReferencesInfo().getReferencesCiCodes())
                    && (!Objects.equals(chapterData.getReferencesInfo().getReferencesCiCodes().size(), module.getModuleDefinition().getReferencesInfo().getReferencesCiCodes().size())
                    || !chapterData.getReferencesInfo().getReferencesCiCodes().containsAll(module.getModuleDefinition().getReferencesInfo().getReferencesCiCodes())))))) {
                module.getModuleDefinition().setReferencesInfo(chapterData.getReferencesInfo());
                handleChapterModule(chapterModuleList, chapterInstance.getId(), chapterData.getId(), Constants.UPDATE_SIGN, Constants.UPDATE_SIGN, true);
            }
            if ((Objects.equals(moduleDefinition.getDataTableForm(), 1) || Objects.equals(moduleDefinition.getDataTableForm(), 2))
                    && (Objects.equals(chapterData.getDataTableForm(), 1) || Objects.equals(chapterData.getDataTableForm(), 2))) {
                List<RowTableContentVo> templateDataTableList = chapterData.getDataTableContent();
                List<String> templateTableKeyList = templateDataTableList.stream().map(row -> row.getName()).collect(Collectors.toList());
                Map<String, RowTableContentVo> templateRowTableMap = templateDataTableList.stream().collect(Collectors.toMap(item -> item.getName(), item -> item));
                List<RowTableContentVo> planDataTableList = moduleDefinition.getDataTableContent();
                // 获取 方案 资产信息项关联classId信息列表
                Map<String, Long> map = new HashMap<>();
                for (RowTableContentVo rowTable : planDataTableList) {
                    if (Objects.equals(rowTable.getType(), 11)) {
                        try {
                            String item = rowTable.getCopyConstraint();
                            JSONObject jsonObject = JSONObject.parseObject(item);
                            map.put(rowTable.getName(), jsonObject.getLong("classId"));
                        } catch (Exception e) {
                            // 转json失败，不做任何处理，下一轮循环
                            log.info(e.getMessage());
                            continue;
                        }
                    }
                }
                // 获取 方案模板 资产信息项关联classId信息列表
                Map<String, Long> planDataTableMap = new HashMap<>();
                if (!CollectionUtils.isEmpty(templateDataTableList)) {
                    for (RowTableContentVo rowTableContentVo : templateDataTableList) {
                        if (Objects.equals(rowTableContentVo.getType(), TableContentTypeEnum.ASSET.getType())) {
                            String name = rowTableContentVo.getName();
                            String copyConstraint = rowTableContentVo.getCopyConstraint();
                            if (!StringUtils.isEmpty(copyConstraint)) {
                                try {
                                    JSONObject jsonObject = JSONObject.parseObject(copyConstraint);
                                    if (jsonObject != null && jsonObject.containsKey("classId")) {
                                        planDataTableMap.put(name, jsonObject.getLong("classId"));
                                    }
                                } catch (Exception e) {
                                    // 转json失败，不做任何处理，下一轮循环
                                    log.info(e.getMessage());
                                    continue;
                                }
                            }
                        }
                    }
                }

                // 获取 方案 绑定资产信息项 信息列表
                Map<String, RowTableContentVo> assetsMap = planDataTableList.stream().filter(rowTable -> Objects.equals(rowTable.getType(), TableContentTypeEnum.BIND_ASSET.getType()))
                        .collect(Collectors.toMap(RowTableContentVo::getName, item -> item));

                if (!Objects.equals(templateDataTableList.size(), planDataTableList.size())) {
                    // dataMap清洗数据
                    Map<String, Boolean> dataMap = new LinkedHashMap<>();
                    for (RowTableContentVo planRowTable : planDataTableList) {
                        RowTableContentVo rowTableContentVo = templateRowTableMap.get(planRowTable.getName());
                        if (rowTableContentVo == null || !Objects.equals(planRowTable.getType(), rowTableContentVo.getType())) {
                            dataMap.put(planRowTable.getName(), false);
                        } else {
                            dataMap.put(planRowTable.getName(), true);
                            templateTableKeyList.remove(planRowTable.getName());
                        }
                    }
                    moduleDefinition.setDataTableContent(templateDataTableList);

                    // 清洗表格数据
                    Map<String, String> filterTableMap = new HashMap<>();
                    for (int i = 0; i < templateDataTableList.size(); i++) {
                        RowTableContentVo templateRow = templateDataTableList.get(i);
                        if (i <= planDataTableList.size() - 1) {
                            RowTableContentVo planRow = planDataTableList.get(i);
                            if (Objects.equals(templateRow.getType(), 12) && !Objects.equals(planRow.getType(), 12)) {
                                module.setData("{}");
                            } else if (!Objects.equals(templateRow.getType(), 12) && Objects.equals(planRow.getType(), 12)) {
                                module.setData("{}");
                            } else if (Objects.equals(templateRow.getType(), 12) && Objects.equals(planRow.getType(), 12)) {
                                String planConstraint = planRow.getCopyConstraint();
                                String templateConstraint = templateRow.getCopyConstraint();
                                JSONObject planJson = JSONObject.parseObject(planConstraint);
                                JSONObject templateJson = JSONObject.parseObject(templateConstraint);
                                Long planClassId = planJson.getLong("classId");
                                Long templateClassId = templateJson.getLong("classId");
                                if (!Objects.equals(planClassId, templateClassId)) {
                                    module.setData("{}");
                                } else if (!Objects.equals(templateRow.getName(), planRow.getName())) {
                                    filterTableMap.put(planRow.getName(), templateRow.getName());
                                }
                            }
                        } else if (Objects.equals(templateRow.getType(), 12)) {
                            module.setData("{}");
                        }
                    }
                    clearDataTable(module, dataMap, map, planDataTableMap, assetsMap, templateTableKeyList, filterTableMap);

                    handleChapterModule(chapterModuleList, chapterInstance.getId(), chapterData.getId(), Constants.UPDATE_SIGN, Constants.UPDATE_SIGN, true);
                } else {
                    boolean sign = true;
                    Map<String, Boolean> dataMap = new LinkedHashMap<>();
                    for (RowTableContentVo planRowTable : planDataTableList) {
                        RowTableContentVo rowTableContentVo = templateRowTableMap.get(planRowTable.getName());
                        if (rowTableContentVo == null || !Objects.equals(planRowTable.getType(), rowTableContentVo.getType())) {
                            dataMap.put(planRowTable.getName(), false);
                        } else {
                            dataMap.put(planRowTable.getName(), true);
                            templateTableKeyList.remove(planRowTable.getName());
                            if (sign) {
                                boolean result = !Objects.equals(rowTableContentVo.getName(), planRowTable.getName()) || !Objects.equals(rowTableContentVo.getType(), planRowTable.getType())
                                        || !Objects.equals(rowTableContentVo.getCopyConstraint(), planRowTable.getCopyConstraint()) || !Objects.equals(rowTableContentVo.getRequired(), planRowTable.getRequired())
                                        || !Objects.equals(rowTableContentVo.getClassId(), planRowTable.getClassId()) || !Objects.equals(rowTableContentVo.getColumnWidth(), planRowTable.getColumnWidth());
                                if (result) {
                                    sign = false;
                                }
                            }
                        }
                    }

                    // 判断顺序是否一致
                    if (sign && CollectionUtils.isEmpty(templateTableKeyList)) {
                        for (int i = 0; i < templateDataTableList.size(); i++) {
                            RowTableContentVo rowTableContentVo = planDataTableList.get(i);
                            if (!Objects.equals(templateDataTableList.get(i).getName(), rowTableContentVo.getName())
                                    || !Objects.equals(templateDataTableList.get(i).getType(), rowTableContentVo.getType())) {
                                sign = false;
                                break;
                            }
                        }
                    }

                    // 清洗表格数据
                    Map<String, String> filterTableMap = new HashMap<>();
                    for (int i = 0; i < templateDataTableList.size(); i++) {
                        RowTableContentVo templateRow = templateDataTableList.get(i);
                        if (i <= planDataTableList.size() - 1) {
                            RowTableContentVo planRow = planDataTableList.get(i);
                            if (Objects.equals(templateRow.getType(), 12) && !Objects.equals(planRow.getType(), 12)) {
                                module.setData("{}");
                            } else if (!Objects.equals(templateRow.getType(), 12) && Objects.equals(planRow.getType(), 12)) {
                                module.setData("{}");
                            } else if (Objects.equals(templateRow.getType(), 12) && Objects.equals(planRow.getType(), 12)) {
                                String planConstraint = planRow.getCopyConstraint();
                                String templateConstraint = templateRow.getCopyConstraint();
                                JSONObject planJson = JSONObject.parseObject(planConstraint);
                                JSONObject templateJson = JSONObject.parseObject(templateConstraint);
                                Long planClassId = planJson.getLong("classId");
                                Long templateClassId = templateJson.getLong("classId");
                                if (!Objects.equals(planClassId, templateClassId)) {
                                    module.setData("{}");
                                } else if (!Objects.equals(templateRow.getName(), planRow.getName())) {
                                    filterTableMap.put(planRow.getName(), templateRow.getName());
                                }
                            }
                        } else if (Objects.equals(templateRow.getType(), 12)) {
                            module.setData("{}");
                        }
                    }

                    clearDataTable(module, dataMap, map, planDataTableMap, assetsMap, templateTableKeyList, filterTableMap);

                    if (!sign || !CollectionUtils.isEmpty(templateTableKeyList)) {
                        moduleDefinition.setDataTableContent(templateDataTableList);
                        handleChapterModule(chapterModuleList, chapterInstance.getId(), chapterData.getId(), Constants.UPDATE_SIGN, Constants.UPDATE_SIGN, true);
                    }
                }
            } else {
                if (!Objects.equals(chapterData.getDataTableForm(), moduleDefinition.getDataTableForm())) {
                    module.setData("{}");
                    if (Objects.equals(chapterData.getDataTableForm(), 3)) {
                        moduleDefinition.setMatrixConfig(chapterData.getMatrixConfig());
                        moduleDefinition.setMatrixRow(chapterData.getMatrixRow());
                        moduleDefinition.setMatrixCol(chapterData.getMatrixCol());
                        moduleDefinition.setDataTableContent(null);
                        handleChapterModule(chapterModuleList, chapterInstance.getId(), chapterData.getId(), Constants.UPDATE_SIGN, Constants.UPDATE_SIGN, true);
                    } else {
                        moduleDefinition.setDataTableContent(chapterData.getDataTableContent());
                        moduleDefinition.setMatrixConfig(null);
                        moduleDefinition.setMatrixRow(null);
                        moduleDefinition.setMatrixCol(null);
                        handleChapterModule(chapterModuleList, chapterInstance.getId(), chapterData.getId(), Constants.UPDATE_SIGN, Constants.UPDATE_SIGN, true);
                    }
                } else if (!Objects.equals(chapterData.getMatrixConfig(), moduleDefinition.getMatrixConfig())){
                    module.setData("{}");
                    moduleDefinition.setMatrixConfig(chapterData.getMatrixConfig());
                    moduleDefinition.setMatrixRow(chapterData.getMatrixRow());
                    moduleDefinition.setMatrixCol(chapterData.getMatrixCol());
                    moduleDefinition.setDataTableContent(null);
                    handleChapterModule(chapterModuleList, chapterInstance.getId(), chapterData.getId(), Constants.UPDATE_SIGN, Constants.UPDATE_SIGN, true);
                } else {
                    if (Objects.equals(chapterData.getMatrixConfig(), 1)) {
                        List<RowTableContentVo> templateMatrixRowList = chapterData.getMatrixRow();
                        List<String> templateTableKeyList = templateMatrixRowList.stream().map(row -> row.getName()).collect(Collectors.toList());
                        Map<String, RowTableContentVo> templateRowTableMap = templateMatrixRowList.stream().collect(Collectors.toMap(item -> item.getName(), item -> item));
                        List<RowTableContentVo> planMatrixRowList = moduleDefinition.getMatrixRow();

                        if (!Objects.equals(templateMatrixRowList.size(), planMatrixRowList.size())) {
                            // dataMap清洗数据
                            Map<String, Boolean> dataMap = new LinkedHashMap<>();
                            for (RowTableContentVo planRowTable : planMatrixRowList) {
                                RowTableContentVo rowTableContentVo = templateRowTableMap.get(planRowTable.getName());
                                if (rowTableContentVo == null || !Objects.equals(planRowTable.getType(), rowTableContentVo.getType())) {
                                    dataMap.put(planRowTable.getName(), false);
                                } else {
                                    dataMap.put(planRowTable.getName(), true);
                                    templateTableKeyList.remove(planRowTable.getName());
                                }
                            }
                            moduleDefinition.setDataTableContent(null);
                            moduleDefinition.setMatrixConfig(chapterData.getMatrixConfig());
                            moduleDefinition.setMatrixRow(templateMatrixRowList);
                            moduleDefinition.setMatrixCol(chapterData.getMatrixCol());

                            clearMatrixDataTable(module, dataMap, templateTableKeyList);

                            handleChapterModule(chapterModuleList, chapterInstance.getId(), chapterData.getId(), Constants.UPDATE_SIGN, Constants.UPDATE_SIGN, true);
                        } else {
                            boolean sign = true;
                            Map<String, Boolean> dataMap = new LinkedHashMap<>();
                            for (RowTableContentVo planRowTable : planMatrixRowList) {
                                RowTableContentVo rowTableContentVo = templateRowTableMap.get(planRowTable.getName());
                                if (rowTableContentVo == null || !Objects.equals(planRowTable.getType(), rowTableContentVo.getType())) {
                                    dataMap.put(planRowTable.getName(), false);
                                } else {
                                    dataMap.put(planRowTable.getName(), true);
                                    templateTableKeyList.remove(planRowTable.getName());
                                    if (sign) {
                                        boolean result = !Objects.equals(rowTableContentVo.getName(), planRowTable.getName()) || !Objects.equals(rowTableContentVo.getType(), planRowTable.getType())
                                                || !Objects.equals(rowTableContentVo.getCopyConstraint(), planRowTable.getCopyConstraint()) || !Objects.equals(rowTableContentVo.getRequired(), planRowTable.getRequired())
                                                || !Objects.equals(rowTableContentVo.getClassId(), planRowTable.getClassId()) || !Objects.equals(rowTableContentVo.getColumnWidth(), planRowTable.getColumnWidth());
                                        if (result) {
                                            sign = false;
                                        }
                                    }
                                }
                            }

                            // 判断顺序是否一致
                            if (sign && CollectionUtils.isEmpty(templateTableKeyList)) {
                                for (int i = 0; i < templateMatrixRowList.size(); i++) {
                                    RowTableContentVo rowTableContentVo = planMatrixRowList.get(i);
                                    if (!Objects.equals(templateMatrixRowList.get(i).getName(), rowTableContentVo.getName())
                                            || !Objects.equals(templateMatrixRowList.get(i).getType(), rowTableContentVo.getType())) {
                                        sign = false;
                                        break;
                                    }
                                }
                            }

                            clearMatrixDataTable(module, dataMap, templateTableKeyList);

                            if (!sign || !CollectionUtils.isEmpty(templateTableKeyList)) {
                                moduleDefinition.setDataTableContent(null);
                                moduleDefinition.setMatrixConfig(chapterData.getMatrixConfig());
                                moduleDefinition.setMatrixRow(templateMatrixRowList);
                                moduleDefinition.setMatrixCol(chapterData.getMatrixCol());
                                handleChapterModule(chapterModuleList, chapterInstance.getId(), chapterData.getId(), Constants.UPDATE_SIGN, Constants.UPDATE_SIGN, true);
                            }
                        }
                    } else {
                        List<RowTableContentVo> templateMatrixColList = chapterData.getMatrixCol();
                        List<String> templateTableKeyList = templateMatrixColList.stream().map(row -> row.getName()).collect(Collectors.toList());
                        Map<String, RowTableContentVo> templateRowTableMap = templateMatrixColList.stream().collect(Collectors.toMap(item -> item.getName(), item -> item));
                        List<RowTableContentVo> planMatrixColList = moduleDefinition.getMatrixCol();

                        if (!Objects.equals(templateMatrixColList.size(), planMatrixColList.size())) {
                            // dataMap清洗数据
                            Map<String, Boolean> dataMap = new LinkedHashMap<>();
                            for (RowTableContentVo planRowTable : planMatrixColList) {
                                RowTableContentVo rowTableContentVo = templateRowTableMap.get(planRowTable.getName());
                                if (rowTableContentVo == null || !Objects.equals(planRowTable.getType(), rowTableContentVo.getType())) {
                                    dataMap.put(planRowTable.getName(), false);
                                } else {
                                    dataMap.put(planRowTable.getName(), true);
                                    templateTableKeyList.remove(planRowTable.getName());
                                }
                            }
                            moduleDefinition.setDataTableContent(null);
                            moduleDefinition.setMatrixConfig(chapterData.getMatrixConfig());
                            moduleDefinition.setMatrixRow(chapterData.getMatrixRow());
                            moduleDefinition.setMatrixCol(templateMatrixColList);

                            clearMatrixDataTable(module, dataMap, templateTableKeyList);

                            handleChapterModule(chapterModuleList, chapterInstance.getId(), chapterData.getId(), Constants.UPDATE_SIGN, Constants.UPDATE_SIGN, true);
                        } else {
                            boolean sign = true;
                            Map<String, Boolean> dataMap = new LinkedHashMap<>();
                            for (RowTableContentVo planRowTable : planMatrixColList) {
                                RowTableContentVo rowTableContentVo = templateRowTableMap.get(planRowTable.getName());
                                if (rowTableContentVo == null || !Objects.equals(planRowTable.getType(), rowTableContentVo.getType())) {
                                    dataMap.put(planRowTable.getName(), false);
                                } else {
                                    dataMap.put(planRowTable.getName(), true);
                                    templateTableKeyList.remove(planRowTable.getName());
                                    if (sign) {
                                        boolean result = !Objects.equals(rowTableContentVo.getName(), planRowTable.getName()) || !Objects.equals(rowTableContentVo.getType(), planRowTable.getType())
                                                || !Objects.equals(rowTableContentVo.getCopyConstraint(), planRowTable.getCopyConstraint()) || !Objects.equals(rowTableContentVo.getRequired(), planRowTable.getRequired())
                                                || !Objects.equals(rowTableContentVo.getClassId(), planRowTable.getClassId()) || !Objects.equals(rowTableContentVo.getColumnWidth(), planRowTable.getColumnWidth());
                                        if (result) {
                                            sign = false;
                                        }
                                    }
                                }
                            }

                            // 判断顺序是否一致
                            if (sign && CollectionUtils.isEmpty(templateTableKeyList)) {
                                for (int i = 0; i < templateMatrixColList.size(); i++) {
                                    RowTableContentVo rowTableContentVo = planMatrixColList.get(i);
                                    if (!Objects.equals(templateMatrixColList.get(i).getName(), rowTableContentVo.getName())
                                            || !Objects.equals(templateMatrixColList.get(i).getType(), rowTableContentVo.getType())) {
                                        sign = false;
                                        break;
                                    }
                                }
                            }

                            clearMatrixDataTable(module, dataMap, templateTableKeyList);

                            if (!sign || !CollectionUtils.isEmpty(templateTableKeyList)) {
                                moduleDefinition.setDataTableContent(null);
                                moduleDefinition.setMatrixConfig(chapterData.getMatrixConfig());
                                moduleDefinition.setMatrixRow(chapterData.getMatrixRow());
                                moduleDefinition.setMatrixCol(templateMatrixColList);
                                handleChapterModule(chapterModuleList, chapterInstance.getId(), chapterData.getId(), Constants.UPDATE_SIGN, Constants.UPDATE_SIGN, true);
                            }
                        }
                    }
                }
            }
            if (!Objects.equals(chapterData.getDataTableForm(), moduleDefinition.getDataTableForm())) {
                moduleDefinition.setDataTableForm(chapterData.getDataTableForm());
                handleChapterModule(chapterModuleList, chapterInstance.getId(), chapterData.getId(), Constants.UPDATE_SIGN, Constants.UPDATE_SIGN, true);
            }
        }
    }

    private void clearMatrixDataTable(ContextModule module, Map<String, Boolean> dataMap, List<String> templateTableKeyList) {
        // 清洗数据
        JSONObject jsonObject = JSONObject.parseObject(module.getData());
        if (jsonObject != null && jsonObject.containsKey(Constants.DATA_SIGN) && !StringUtils.isEmpty(jsonObject.getString(Constants.DATA_SIGN))) {
            String content = jsonObject.getString(Constants.DATA_SIGN);
            JSONArray jsonArray = JSONArray.parseArray(content);
            JSONArray newJsonArray = new JSONArray();
            for(int i = 0; i< jsonArray.size(); i++){
                JSONObject tableData = JSONObject.parseObject(jsonArray.get(i).toString());
                List<String> planDataTableKeyList = new ArrayList<>(tableData.keySet());
                JSONObject dataJson = new JSONObject();
                for (int j = 0; j < planDataTableKeyList.size(); j++) {
                    String planKey = planDataTableKeyList.get(j);
                    Boolean result = dataMap.get(planKey);
                    if (result == null || result) {
                        dataJson.put(planKey, tableData.get(planKey));
                    }
                }
                // 如果方案模板表格新加行数据对应扩展
                for (String templateTableKey : templateTableKeyList) {
                    dataJson.put(templateTableKey, "");
                }
                newJsonArray.add(dataJson);
            }
            JSONObject newJSONObject = new JSONObject();
            newJSONObject.put("data", newJsonArray);
            module.setData(newJSONObject.toJSONString());
        }
    }

    private void clearDataTable(ContextModule module, Map<String, Boolean> dataMap, Map<String, Long> map, Map<String, Long> planDataTableMap,
                                Map<String, RowTableContentVo> assetsMap, List<String> templateTableKeyList, Map<String, String> filterTableMap) {
        // 清洗数据
        JSONObject jsonObject = JSONObject.parseObject(module.getData());
        if (jsonObject != null && jsonObject.containsKey(Constants.DATA_SIGN) && !StringUtils.isEmpty(jsonObject.getString(Constants.DATA_SIGN))) {
            String content = jsonObject.getString(Constants.DATA_SIGN);
            JSONArray jsonArray = JSONArray.parseArray(content);
            JSONArray newJsonArray = new JSONArray();
            for(int i = 0; i< jsonArray.size(); i++){
                JSONObject tableData = JSONObject.parseObject(jsonArray.get(i).toString());
                List<String> planDataTableKeyList = new ArrayList<>(tableData.keySet());
                JSONObject dataJson = new JSONObject();
                for (int j = 0; j < planDataTableKeyList.size(); j++) {
                    String planKey = planDataTableKeyList.get(j);
                    Boolean result = dataMap.get(planKey);
                    if (result == null || result) {
                        Long classId = map.get(planKey);
                        if (classId != null) {
                            if (!Objects.equals(planDataTableMap.get(planKey), classId)) {
                                dataJson.put(planKey, "");
                            } else {
                                dataJson.put(planKey, tableData.get(planKey));
                            }
                        } else if (assetsMap.get(planKey) != null) {
                            dataJson.put(planKey, "");
                        } else {
                            dataJson.put(planKey, tableData.get(planKey));
                        }
                    } else {
                        if (filterTableMap != null && !StringUtils.isEmpty(filterTableMap.get(planKey))) {
                            String planTableKey = filterTableMap.get(planKey);
                            dataJson.put(planTableKey, tableData.get(planKey));
                        }
                    }
                }
                // 如果方案模板表格新加行数据对应扩展
                for (String templateTableKey : templateTableKeyList) {
                    if (filterTableMap == null || !filterTableMap.values().contains(templateTableKey)) {
                        dataJson.put(templateTableKey, "");
                    }
                }
                newJsonArray.add(dataJson);
            }
            JSONObject newJSONObject = new JSONObject();
            newJSONObject.put("data", newJsonArray);
            module.setData(newJSONObject.toJSONString());
        }
    }

    /**
     *
     * @param chapterData   模板内容块数据
     * @param module        方案内容块数据
     */
    private void ValidateAttachmentChange(PlanTemplateChapterData chapterData, ContextModule module, ChapterInstance chapterInstance, List<ChapterModuleVO> chapterModuleList) {
        if (StringUtils.isNotEmpty(chapterData.getAppendixName()) && !chapterData.getAppendixName().equals(module.getModuleDefinition().getAppendixName())) {
            module.getModuleDefinition().setAppendixName(chapterData.getAppendixName());
            handleChapterModule(chapterModuleList, chapterInstance.getId(), chapterData.getId(), Constants.UPDATE_SIGN, Constants.UPDATE_SIGN, true);
        }
        if (!chapterData.getAppendixRequired().equals(module.getModuleDefinition().getAppendixRequired())) {
            module.getModuleDefinition().setAppendixRequired(chapterData.getAppendixRequired());
            handleChapterModule(chapterModuleList, chapterInstance.getId(), chapterData.getId(), Constants.UPDATE_SIGN, Constants.UPDATE_SIGN, true);
        }

        /*if (!chapterData.getAppendixShow().equals(module.getModuleDefinition().getAppendixShow())) {
            module.getModuleDefinition().setAppendixShow(chapterData.getAppendixShow());
            handleChapterModule(chapterModuleList, chapterInstance.getId(), chapterData.getId(), Constants.UPDATE_SIGN, Constants.UPDATE_SIGN, true);
        }*/
        if (!chapterData.getAppendixContent().equals(module.getModuleDefinition().getAppendixContent())) {
            module.getModuleDefinition().setAppendixContent(chapterData.getAppendixContent());
            handleChapterModule(chapterModuleList, chapterInstance.getId(), chapterData.getId(), Constants.UPDATE_SIGN, Constants.UPDATE_SIGN, true);
        }
        if ((chapterData.getReferencesInfo() != null && module.getModuleDefinition().getReferencesInfo() == null)
                || (chapterData.getReferencesInfo() == null && module.getModuleDefinition().getReferencesInfo() != null)
                || (chapterData.getReferencesInfo() != null && module.getModuleDefinition().getReferencesInfo() != null
                && (!Objects.equals(chapterData.getReferencesInfo().getReferencesClassCode(), module.getModuleDefinition().getReferencesInfo().getReferencesClassCode())
                || (CollectionUtils.isEmpty(chapterData.getReferencesInfo().getReferencesCiCodes()) && !CollectionUtils.isEmpty(module.getModuleDefinition().getReferencesInfo().getReferencesCiCodes()))
                || (!CollectionUtils.isEmpty(chapterData.getReferencesInfo().getReferencesCiCodes()) && CollectionUtils.isEmpty(module.getModuleDefinition().getReferencesInfo().getReferencesCiCodes()))
                || (!CollectionUtils.isEmpty(chapterData.getReferencesInfo().getReferencesCiCodes()) && !CollectionUtils.isEmpty(module.getModuleDefinition().getReferencesInfo().getReferencesCiCodes())
                && (!Objects.equals(chapterData.getReferencesInfo().getReferencesCiCodes().size(), module.getModuleDefinition().getReferencesInfo().getReferencesCiCodes().size())
                || !chapterData.getReferencesInfo().getReferencesCiCodes().containsAll(module.getModuleDefinition().getReferencesInfo().getReferencesCiCodes())))))) {
            module.getModuleDefinition().setReferencesInfo(chapterData.getReferencesInfo());
            handleChapterModule(chapterModuleList, chapterInstance.getId(), chapterData.getId(), Constants.UPDATE_SIGN, Constants.UPDATE_SIGN, true);
        }
    }

    /**
     *
     * @param chapterData 模板内容块数据
     * @param module      方案内容块数据
     */
    private void ValidateTextChange(PlanTemplateChapterData chapterData, ContextModule module, ChapterInstance chapterInstance, List<ChapterModuleVO> chapterModuleList) {
        if (StringUtils.isNotEmpty(chapterData.getRichTextName()) && !chapterData.getRichTextName().equals(module.getModuleDefinition().getRichTextName())) {
            module.getModuleDefinition().setRichTextName(chapterData.getRichTextName());
            handleChapterModule(chapterModuleList, chapterInstance.getId(), chapterData.getId(), Constants.UPDATE_SIGN, Constants.UPDATE_SIGN, true);
        }

        if (!chapterData.getRichTextRequired().equals(module.getModuleDefinition().getRichTextRequired())) {
            module.getModuleDefinition().setRichTextRequired(chapterData.getRichTextRequired());
            handleChapterModule(chapterModuleList, chapterInstance.getId(), chapterData.getId(), Constants.UPDATE_SIGN, Constants.UPDATE_SIGN, true);
        }
        /*if (!chapterData.getRichTextRemark().equals(module.getModuleDefinition().getRichTextRemark())) {
            module.getModuleDefinition().setRichTextRemark(chapterData.getRichTextRemark());
            handleChapterModule(chapterModuleList, chapterInstance.getId(), chapterData.getId(), Constants.UPDATE_SIGN, Constants.UPDATE_SIGN, true);
        }*/

        if (!chapterData.getRichTextContent().equals(module.getModuleDefinition().getRichTextContent())) {
            module.getModuleDefinition().setRichTextContent(chapterData.getRichTextContent());
            handleChapterModule(chapterModuleList, chapterInstance.getId(), chapterData.getId(), Constants.UPDATE_SIGN, Constants.UPDATE_SIGN, true);
        }

        JSONObject jsonObject = JSON.parseObject(module.getData());
        String content = jsonObject.getString("data");
        boolean result = (!StringUtils.isEmpty(chapterData.getInitRichText()) && !StringUtils.isEmpty(content)
                && !Objects.equals(chapterData.getInitRichText(), content) && Objects.equals(content, module.getModuleDefinition().getInitRichText()))
                || (!StringUtils.isEmpty(chapterData.getInitRichText()) && StringUtils.isEmpty(content));
        if (result) {
            if (StringUtils.isEmpty(content)) {
                module.getModuleDefinition().setInitRichText(chapterData.getInitRichText());
            }
            jsonObject.put("data", chapterData.getInitRichText());
            module.setData(jsonObject.toJSONString());
            handleChapterModule(chapterModuleList, chapterInstance.getId(), chapterData.getId(), Constants.UPDATE_SIGN, Constants.UPDATE_SIGN, true);
        }

        if ((chapterData.getReferencesInfo() != null && module.getModuleDefinition().getReferencesInfo() == null)
                || (chapterData.getReferencesInfo() == null && module.getModuleDefinition().getReferencesInfo() != null)
                || (chapterData.getReferencesInfo() != null && module.getModuleDefinition().getReferencesInfo() != null
                && (!Objects.equals(chapterData.getReferencesInfo().getReferencesClassCode(), module.getModuleDefinition().getReferencesInfo().getReferencesClassCode())
                || (CollectionUtils.isEmpty(chapterData.getReferencesInfo().getReferencesCiCodes()) && !CollectionUtils.isEmpty(module.getModuleDefinition().getReferencesInfo().getReferencesCiCodes()))
                || (!CollectionUtils.isEmpty(chapterData.getReferencesInfo().getReferencesCiCodes()) && CollectionUtils.isEmpty(module.getModuleDefinition().getReferencesInfo().getReferencesCiCodes()))
                || (!CollectionUtils.isEmpty(chapterData.getReferencesInfo().getReferencesCiCodes()) && !CollectionUtils.isEmpty(module.getModuleDefinition().getReferencesInfo().getReferencesCiCodes())
                && (!Objects.equals(chapterData.getReferencesInfo().getReferencesCiCodes().size(), module.getModuleDefinition().getReferencesInfo().getReferencesCiCodes().size())
                || !chapterData.getReferencesInfo().getReferencesCiCodes().containsAll(module.getModuleDefinition().getReferencesInfo().getReferencesCiCodes())))))) {
            module.getModuleDefinition().setReferencesInfo(chapterData.getReferencesInfo());
            handleChapterModule(chapterModuleList, chapterInstance.getId(), chapterData.getId(), Constants.UPDATE_SIGN, Constants.UPDATE_SIGN, true);
        }
    }

    /**
     * 处理方案删除的章节和模块，添加标识
     * @param chapterIdList
     * @param chapterInstanceMap
     * @param chapterModuleList
     */
    private void handleDeleteChapter(List<Long> chapterIdList, Map<Long, ChapterInstance> chapterInstanceMap, List<ChapterModuleVO> chapterModuleList) {
        if (!CollectionUtils.isEmpty(chapterIdList)) {
            List<ChapterInstance> deleteChapterList = new ArrayList<>();
            List<ChapterContext> chapterContextList = new ArrayList<>();
            for (Long chapterId : chapterIdList)  {
                ChapterInstance chapterInstance = chapterInstanceMap.get(chapterId);
                boolean result = false;
                ChapterContext chapterContext = null;
                if (chapterInstance != null && !Objects.equals(chapterInstance.getTemplateDelete(), 1)) {
                    chapterInstance.setTemplateDelete(1);
                    deleteChapterList.add(chapterInstance);
                    result = true;
                    chapterContext = chapterContextDao.getById(chapterInstance.getId());
                }

                if (chapterContext != null && !CollectionUtils.isEmpty(chapterContext.getModuleList())) {
                    List<ContextModule> moduleList = chapterContext.getModuleList();
                    for (ContextModule context : moduleList) {
                        if (!Objects.equals(context.getTemplateDelete(), 1)) {
                            context.setTemplateDelete(1);
                            // 处理模块是删除/新增/修改
                            /*ChapterModuleVO chapterModuleVO = new ChapterModuleVO();
                            chapterModuleVO.setChapterId(chapterInstance.getId());
                            chapterModuleVO.setModuleId(context.getId());
                            chapterModuleVO.setSign(0);
                            chapterModuleList.add(chapterModuleVO);*/
                            handleChapterModule(chapterModuleList, chapterInstance.getId(), context.getId(), Constants.DELETE_SIGN, Constants.DELETE_SIGN, true);
                        }
                    }
                    chapterContextList.add(chapterContext);
                } else {
                    if (result) {
                        /*ChapterModuleVO chapterModuleVO = new ChapterModuleVO();
                        chapterModuleVO.setChapterId(chapterInstance.getId());
                        chapterModuleVO.setSign(0);
                        chapterModuleList.add(chapterModuleVO);*/
                        handleChapterModule(chapterModuleList, chapterInstance.getId(), null, Constants.DELETE_SIGN, null, false);
                    }
                }

            }
            // 控制章节对应模板已删除
            if (!CollectionUtils.isEmpty(deleteChapterList)) {
                planChapterInstanceDao.saveOrUpdateBatch(deleteChapterList);
            }
            // 控制章节模块对应模板已删除
            if (!CollectionUtils.isEmpty(chapterContextList)) {
                chapterContextDao.saveOrUpdateBatch(chapterContextList);
            }
        }
    }

    private void handleChapterModule(List<ChapterModuleVO> chapterModuleList, Long chapterId, Long moduleId, Integer chapterSign, Integer moduleSign, Boolean sign) {
        Map<Long, ChapterModuleVO> chapterModuleMap = chapterModuleList.stream().collect(Collectors.toMap(item -> item.getChapterId(), item -> item));
        if (CollectionUtils.isEmpty(chapterModuleMap)) {
            ChapterModuleVO chapterModuleVO = new ChapterModuleVO();
            chapterModuleVO.setChapterId(chapterId);
            chapterModuleVO.setChapterSign(chapterSign);
            chapterModuleList.add(chapterModuleVO);
            if (sign) {
                List<ModuleVO> moduleInfoList = new ArrayList<>();
                ModuleVO moduleVO = new ModuleVO();
                moduleVO.setModuleId(moduleId);
                moduleVO.setModuleSign(moduleSign);
                moduleInfoList.add(moduleVO);
                chapterModuleVO.setModuleList(moduleInfoList);
            }
        } else {
            ChapterModuleVO chapterModuleVO = chapterModuleMap.get(chapterId);
            if (chapterModuleVO == null) {
                chapterModuleVO = new ChapterModuleVO();
                chapterModuleVO.setChapterId(chapterId);
                chapterModuleVO.setChapterSign(chapterSign);
                chapterModuleList.add(chapterModuleVO);
                if (sign) {
                    List<ModuleVO> moduleInfoList = new ArrayList<>();
                    ModuleVO moduleVO = new ModuleVO();
                    moduleVO.setModuleId(moduleId);
                    moduleVO.setModuleSign(moduleSign);
                    moduleInfoList.add(moduleVO);
                    chapterModuleVO.setModuleList(moduleInfoList);
                }
            } else {
                if (sign) {
                    List<ModuleVO> moduleContentList = chapterModuleVO.getModuleList();
                    if (CollectionUtils.isEmpty(moduleContentList)) {
                        moduleContentList = new ArrayList<>();
                    } else {
                        List<Long> moduleList = moduleContentList.stream().map(moduleVO -> moduleVO.getModuleId()).collect(Collectors.toList());
                        if (moduleList.contains(moduleId))  {
                            return;
                        }
                    }
                    ModuleVO moduleVO = new ModuleVO();
                    moduleVO.setModuleId(moduleId);
                    moduleVO.setModuleSign(moduleSign);
                    moduleContentList.add(moduleVO);
                    chapterModuleVO.setModuleList(moduleContentList);
                }
            }
        }
    }

    private void handleChildSerialNum(ChapterInstance chapter, List<ChapterInstance> childChapterInstance) {
        BoolQueryBuilder levelQuery = QueryBuilders.boolQuery();
        levelQuery.must(QueryBuilders.termQuery("parentId", chapter.getId()));
        levelQuery.must(QueryBuilders.termQuery("deleted", false));
        List<ChapterInstance> chapterInstanceList = planChapterInstanceDao.getListByQuery(levelQuery);
        for (ChapterInstance childChapter : chapterInstanceList) {
            String serialNum = childChapter.getSerialNum();
            String[] split = serialNum.split("\\.");
            Integer value = Integer.valueOf(split[childChapter.getLevel() - 1]);
            childChapter.setSerialNum(chapter.getSerialNum() + "." + String.valueOf(value));
            childChapterInstance.add(childChapter);

            handleChildSerialNum(childChapter, childChapterInstance);
        }
    }

    private Boolean compareModuleOption(List<PlanTemplateChapterData> chapterDataList, Map<Long, ContextModule> chapterInstanceMap) {
        for (PlanTemplateChapterData templateChapterData : chapterDataList) {
            ContextModule contextModule = chapterInstanceMap.get(templateChapterData.getId());
            if (contextModule == null) {
                continue;
            }
            PlanTemplateChapterData moduleDefinition = contextModule.getModuleDefinition();
            Integer type = moduleDefinition.getType();
            if (Objects.equals(type, ChapterDataTypeEnum.PRODUCT.getDataType())) {
                boolean result = !Objects.equals(templateChapterData.getProductName(), moduleDefinition.getProductName())
                        || !Objects.equals(templateChapterData.getProductRequired(), moduleDefinition.getProductRequired())
                        || !Objects.equals(templateChapterData.getProductControl(), moduleDefinition.getProductControl())
                        //|| !Objects.equals(templateChapterData.getProductType(), moduleDefinition.getProductType())
                        || !Objects.equals(templateChapterData.getDiagramProductType(), moduleDefinition.getDiagramProductType())
                        ||(templateChapterData.getReferencesInfo() != null && moduleDefinition.getReferencesInfo() == null)
                        || (templateChapterData.getReferencesInfo() == null && moduleDefinition.getReferencesInfo() != null)
                        || (templateChapterData.getReferencesInfo() != null && moduleDefinition.getReferencesInfo() != null
                            && (!Objects.equals(templateChapterData.getReferencesInfo().getReferencesClassCode(), moduleDefinition.getReferencesInfo().getReferencesClassCode())
                                || (CollectionUtils.isEmpty(templateChapterData.getReferencesInfo().getReferencesCiCodes()) && !CollectionUtils.isEmpty(moduleDefinition.getReferencesInfo().getReferencesCiCodes()))
                                || (!CollectionUtils.isEmpty(templateChapterData.getReferencesInfo().getReferencesCiCodes()) && CollectionUtils.isEmpty(moduleDefinition.getReferencesInfo().getReferencesCiCodes()))
                                || (!CollectionUtils.isEmpty(templateChapterData.getReferencesInfo().getReferencesCiCodes()) && !CollectionUtils.isEmpty(moduleDefinition.getReferencesInfo().getReferencesCiCodes())
                                    && (!Objects.equals(templateChapterData.getReferencesInfo().getReferencesCiCodes().size(), moduleDefinition.getReferencesInfo().getReferencesCiCodes().size())
                                        || !templateChapterData.getReferencesInfo().getReferencesCiCodes().containsAll(moduleDefinition.getReferencesInfo().getReferencesCiCodes())))));
                if (result) {
                    return result;
                }
            } else if (Objects.equals(type, ChapterDataTypeEnum.DATA_TABLE.getDataType())) {
                boolean baseResult = !Objects.equals(templateChapterData.getDataTableName(), moduleDefinition.getDataTableName())
                        || !Objects.equals(templateChapterData.getDataTableForm(), moduleDefinition.getDataTableForm())
                        || !Objects.equals(templateChapterData.getDataTableRequired(), moduleDefinition.getDataTableRequired())
                        || !Objects.equals(templateChapterData.getUserAddRow(), moduleDefinition.getUserAddRow())
                        || !Objects.equals(templateChapterData.getDataTableRemarkStatus(), moduleDefinition.getDataTableRemarkStatus())
                        || !Objects.equals(templateChapterData.getDataTableRemarkInfo(), moduleDefinition.getDataTableRemarkInfo())
                        ||(templateChapterData.getReferencesInfo() != null && moduleDefinition.getReferencesInfo() == null)
                        || (templateChapterData.getReferencesInfo() == null && moduleDefinition.getReferencesInfo() != null)
                        || (templateChapterData.getReferencesInfo() != null && moduleDefinition.getReferencesInfo() != null
                            && (!Objects.equals(templateChapterData.getReferencesInfo().getReferencesClassCode(), moduleDefinition.getReferencesInfo().getReferencesClassCode())
                                || (CollectionUtils.isEmpty(templateChapterData.getReferencesInfo().getReferencesCiCodes()) && !CollectionUtils.isEmpty(moduleDefinition.getReferencesInfo().getReferencesCiCodes()))
                                || (!CollectionUtils.isEmpty(templateChapterData.getReferencesInfo().getReferencesCiCodes()) && CollectionUtils.isEmpty(moduleDefinition.getReferencesInfo().getReferencesCiCodes()))
                                || (!CollectionUtils.isEmpty(templateChapterData.getReferencesInfo().getReferencesCiCodes()) && !CollectionUtils.isEmpty(moduleDefinition.getReferencesInfo().getReferencesCiCodes())
                                    && (!Objects.equals(templateChapterData.getReferencesInfo().getReferencesCiCodes().size(), moduleDefinition.getReferencesInfo().getReferencesCiCodes().size())
                                    || !templateChapterData.getReferencesInfo().getReferencesCiCodes().containsAll(moduleDefinition.getReferencesInfo().getReferencesCiCodes())))));
                if (baseResult) {
                    return baseResult;
                }
                if (Objects.equals(templateChapterData.getDataTableForm(), 1) || Objects.equals(templateChapterData.getDataTableForm(), 2)) {
                    List<RowTableContentVo> templateDataTableList = templateChapterData.getDataTableContent();
                    List<RowTableContentVo> planDataTableList = moduleDefinition.getDataTableContent();
                    if (!Objects.equals(templateDataTableList.size(), planDataTableList.size())) {
                        return true;
                    } else {
                        for (int i = 0; i < templateDataTableList.size(); i++) {
                            RowTableContentVo templateRowTable = templateDataTableList.get(i);
                            RowTableContentVo planRowTable = planDataTableList.get(i);
                            boolean tableResult = !Objects.equals(templateRowTable.getName(), planRowTable.getName())
                                    || !Objects.equals(templateRowTable.getType(), planRowTable.getType())
                                    || !Objects.equals(templateRowTable.getCopyConstraint(), planRowTable.getCopyConstraint())
                                    || !Objects.equals(templateRowTable.getRequired(), planRowTable.getRequired())
                                    || !Objects.equals(templateRowTable.getClassId(), planRowTable.getClassId())
                                    || !Objects.equals(templateRowTable.getColumnWidth(), planRowTable.getColumnWidth());
                            if (tableResult) {
                                return tableResult;
                            }
                        }
                    }
                } else if (Objects.equals(templateChapterData.getDataTableForm(), 3)) {
                    if (!Objects.equals(templateChapterData.getMatrixConfig(), moduleDefinition.getMatrixConfig())) {
                        return true;
                    }
                    List<RowTableContentVo> templateMatrixRowList = templateChapterData.getMatrixRow();
                    List<RowTableContentVo> templateMatrixColList = templateChapterData.getMatrixCol();
                    List<RowTableContentVo> planMatrixRowList = moduleDefinition.getMatrixRow();
                    List<RowTableContentVo> planMatrixColList = moduleDefinition.getMatrixCol();
                    if (Objects.equals(templateChapterData.getMatrixConfig(), 1)) {
                        if (!Objects.equals(templateMatrixRowList.size(), planMatrixRowList.size())) {
                            return true;
                        } else {
                            for (int i = 0; i < templateMatrixRowList.size(); i++) {
                                RowTableContentVo templateRowTable = templateMatrixRowList.get(i);
                                RowTableContentVo planRowTable = planMatrixRowList.get(i);
                                boolean tableResult = !Objects.equals(templateRowTable.getName(), planRowTable.getName())
                                        || !Objects.equals(templateRowTable.getType(), planRowTable.getType())
                                        || !Objects.equals(templateRowTable.getCopyConstraint(), planRowTable.getCopyConstraint())
                                        || !Objects.equals(templateRowTable.getRequired(), planRowTable.getRequired())
                                        || !Objects.equals(templateRowTable.getClassId(), planRowTable.getClassId())
                                        || !Objects.equals(templateRowTable.getColumnWidth(), planRowTable.getColumnWidth());
                                if (tableResult) {
                                    return tableResult;
                                }
                            }
                        }
                    } else {
                        if (!Objects.equals(templateMatrixColList.size(), planMatrixColList.size())) {
                            return true;
                        } else {
                            for (int i = 0; i < templateMatrixColList.size(); i++) {
                                RowTableContentVo templateRowTable = templateMatrixColList.get(i);
                                RowTableContentVo planRowTable = planMatrixColList.get(i);
                                boolean tableResult = !Objects.equals(templateRowTable.getName(), planRowTable.getName())
                                        || !Objects.equals(templateRowTable.getType(), planRowTable.getType())
                                        || !Objects.equals(templateRowTable.getCopyConstraint(), planRowTable.getCopyConstraint())
                                        || !Objects.equals(templateRowTable.getRequired(), planRowTable.getRequired())
                                        || !Objects.equals(templateRowTable.getClassId(), planRowTable.getClassId())
                                        || !Objects.equals(templateRowTable.getColumnWidth(), planRowTable.getColumnWidth());
                                if (tableResult) {
                                    return tableResult;
                                }
                            }
                        }
                    }
                }
            } else if (Objects.equals(type, ChapterDataTypeEnum.RICH_TEXT.getDataType())) {
                JSONObject jsonObject = JSON.parseObject(contextModule.getData());
                String content = jsonObject.getString("data");
                boolean result = !Objects.equals(templateChapterData.getRichTextName(), moduleDefinition.getRichTextName())
                        || !Objects.equals(templateChapterData.getRichTextRequired(), moduleDefinition.getRichTextRequired())
                        //|| !Objects.equals(templateChapterData.getRichTextRemark(), moduleDefinition.getRichTextRemark())
                        || !Objects.equals(templateChapterData.getRichTextContent(), moduleDefinition.getRichTextContent())
                        || ((!StringUtils.isEmpty(templateChapterData.getInitRichText()) && !StringUtils.isEmpty(content)
                        && !Objects.equals(templateChapterData.getInitRichText(), content) && Objects.equals(content, moduleDefinition.getInitRichText()))
                        || (!StringUtils.isEmpty(templateChapterData.getInitRichText()) && StringUtils.isEmpty(content)))
                        ||(templateChapterData.getReferencesInfo() != null && moduleDefinition.getReferencesInfo() == null)
                        || (templateChapterData.getReferencesInfo() == null && moduleDefinition.getReferencesInfo() != null)
                        || (templateChapterData.getReferencesInfo() != null && moduleDefinition.getReferencesInfo() != null
                            && (!Objects.equals(templateChapterData.getReferencesInfo().getReferencesClassCode(), moduleDefinition.getReferencesInfo().getReferencesClassCode())
                                || (CollectionUtils.isEmpty(templateChapterData.getReferencesInfo().getReferencesCiCodes()) && !CollectionUtils.isEmpty(moduleDefinition.getReferencesInfo().getReferencesCiCodes()))
                                || (!CollectionUtils.isEmpty(templateChapterData.getReferencesInfo().getReferencesCiCodes()) && CollectionUtils.isEmpty(moduleDefinition.getReferencesInfo().getReferencesCiCodes()))
                                || (!CollectionUtils.isEmpty(templateChapterData.getReferencesInfo().getReferencesCiCodes()) && !CollectionUtils.isEmpty(moduleDefinition.getReferencesInfo().getReferencesCiCodes())
                                    && (!Objects.equals(templateChapterData.getReferencesInfo().getReferencesCiCodes().size(), moduleDefinition.getReferencesInfo().getReferencesCiCodes().size())
                                        || !templateChapterData.getReferencesInfo().getReferencesCiCodes().containsAll(moduleDefinition.getReferencesInfo().getReferencesCiCodes())))));

                if (result) {
                    return result;
                }
            } else if (Objects.equals(type, ChapterDataTypeEnum.DATA_SET.getDataType())) {
                boolean result = !Objects.equals(templateChapterData.getDataSetName(), moduleDefinition.getDataSetName())
                        || !Objects.equals(templateChapterData.getDataSetRequired(), moduleDefinition.getDataSetRequired())
                        || !Objects.equals(templateChapterData.getDataSetId(), moduleDefinition.getDataSetId())
                        ||(templateChapterData.getReferencesInfo() != null && moduleDefinition.getReferencesInfo() == null)
                        || (templateChapterData.getReferencesInfo() == null && moduleDefinition.getReferencesInfo() != null)
                        || (templateChapterData.getReferencesInfo() != null && moduleDefinition.getReferencesInfo() != null
                            && (!Objects.equals(templateChapterData.getReferencesInfo().getReferencesClassCode(), moduleDefinition.getReferencesInfo().getReferencesClassCode())
                                || (CollectionUtils.isEmpty(templateChapterData.getReferencesInfo().getReferencesCiCodes()) && !CollectionUtils.isEmpty(moduleDefinition.getReferencesInfo().getReferencesCiCodes()))
                                || (!CollectionUtils.isEmpty(templateChapterData.getReferencesInfo().getReferencesCiCodes()) && CollectionUtils.isEmpty(moduleDefinition.getReferencesInfo().getReferencesCiCodes()))
                                || (!CollectionUtils.isEmpty(templateChapterData.getReferencesInfo().getReferencesCiCodes()) && !CollectionUtils.isEmpty(moduleDefinition.getReferencesInfo().getReferencesCiCodes())
                                    && (!Objects.equals(templateChapterData.getReferencesInfo().getReferencesCiCodes().size(), moduleDefinition.getReferencesInfo().getReferencesCiCodes().size())
                                        || !templateChapterData.getReferencesInfo().getReferencesCiCodes().containsAll(moduleDefinition.getReferencesInfo().getReferencesCiCodes())))));
                if (result) {
                    return result;
                }
            } else if (Objects.equals(type, ChapterDataTypeEnum.APPENDIX.getDataType())) {
                boolean result = !Objects.equals(templateChapterData.getAppendixName(), moduleDefinition.getAppendixName())
                        || !Objects.equals(templateChapterData.getAppendixRequired(), moduleDefinition.getAppendixRequired())
                        //|| !Objects.equals(templateChapterData.getAppendixShow(), moduleDefinition.getAppendixShow())
                        || !Objects.equals(templateChapterData.getAppendixContent(), moduleDefinition.getAppendixContent())
                        ||(templateChapterData.getReferencesInfo() != null && moduleDefinition.getReferencesInfo() == null)
                        || (templateChapterData.getReferencesInfo() == null && moduleDefinition.getReferencesInfo() != null)
                        || (templateChapterData.getReferencesInfo() != null && moduleDefinition.getReferencesInfo() != null
                            && (!Objects.equals(templateChapterData.getReferencesInfo().getReferencesClassCode(), moduleDefinition.getReferencesInfo().getReferencesClassCode())
                                || (CollectionUtils.isEmpty(templateChapterData.getReferencesInfo().getReferencesCiCodes()) && !CollectionUtils.isEmpty(moduleDefinition.getReferencesInfo().getReferencesCiCodes()))
                                || (!CollectionUtils.isEmpty(templateChapterData.getReferencesInfo().getReferencesCiCodes()) && CollectionUtils.isEmpty(moduleDefinition.getReferencesInfo().getReferencesCiCodes()))
                                || (!CollectionUtils.isEmpty(templateChapterData.getReferencesInfo().getReferencesCiCodes()) && !CollectionUtils.isEmpty(moduleDefinition.getReferencesInfo().getReferencesCiCodes())
                                    && (!Objects.equals(templateChapterData.getReferencesInfo().getReferencesCiCodes().size(), moduleDefinition.getReferencesInfo().getReferencesCiCodes().size())
                                        || !templateChapterData.getReferencesInfo().getReferencesCiCodes().containsAll(moduleDefinition.getReferencesInfo().getReferencesCiCodes())))));
                if (result) {
                    return result;
                }
            }
        }
        return null;
    }

    private Boolean handlerPlanTemplate(List<PlanTemplateChapter> chapterTemplateList, Map<Long, ChapterInstance> chapterInstanceMap, SysUser sysUser) {
        // 验证名称是否一致
        for (PlanTemplateChapter templateChapter : chapterTemplateList) {
            ChapterInstance chapterInstance = chapterInstanceMap.get(templateChapter.getId());
            if (chapterInstance == null) {
                continue;
            }
            PlanModuleDelete planModule = new PlanModuleDelete();
            planModule.setPlanId(chapterInstance.getPlanId());
            planModule.setTemplateChapterId(chapterInstance.getTemplateId());
            PlanModuleDelete planModuleDelete = planModuleDeleteService.getPlanModuleDelete(planModule, sysUser);
            if (planModuleDelete != null) {
                continue;
            }
            boolean modifyNameByUser = Constants.CHAPTER_NAME_UPDATE_BY_USER.equals(chapterInstance.getModifyNameType());
            //用户没改过方案章节名称时，才进行模板章节名称与方案章节名称对比
            if (!modifyNameByUser && !Objects.equals(chapterInstance.getName(), templateChapter.getChapterName())) {
                return true;
            }
            String required = chapterInstance.getRequired() ? "1" : "0";
            if (!Objects.equals(templateChapter.getRequired(), required)) {
                return true;
            }
            List<ChapterResource> planResource = cjResourceDaoService.getPlanResource(templateChapter.getPlanTemplateId(), templateChapter.getId());
            if ((CollectionUtils.isEmpty(planResource) && !CollectionUtils.isEmpty(chapterInstance.getChapterResources()))
                    || (!CollectionUtils.isEmpty(planResource) && CollectionUtils.isEmpty(chapterInstance.getChapterResources()))) {
                return true;
            }
            if (!CollectionUtils.isEmpty(planResource) && !CollectionUtils.isEmpty(chapterInstance.getChapterResources())) {
                if (!Objects.equals(planResource.size(), chapterInstance.getChapterResources().size())) {
                    return true;
                } else {
                    List<Long> templateResource = planResource.stream().map(resource -> resource.getId()).collect(Collectors.toList());
                    List<Long> planResourceInfo = chapterInstance.getChapterResources().stream().map(resource -> resource.getId()).collect(Collectors.toList());
                    if (!templateResource.containsAll(planResourceInfo)) {
                        return true;
                    }
                }
            }

            List<PlanTemplateIntroduceChapterVo> templateIntroduceList = templateChapter.getPlanTemplateIntroduceChapterVoList();
            List<PlanTemplateIntroduceChapterVo> planIntroduceList = chapterInstance.getPlanTemplateIntroduceChapterVoList();
            if ((CollectionUtils.isEmpty(templateIntroduceList) && !CollectionUtils.isEmpty(planIntroduceList))
                    || (!CollectionUtils.isEmpty(templateIntroduceList) && CollectionUtils.isEmpty(planIntroduceList))) {
                return true;
            }
            if (!CollectionUtils.isEmpty(templateIntroduceList) && !CollectionUtils.isEmpty(planIntroduceList)) {
                if (!Objects.equals(templateIntroduceList.size(), planIntroduceList.size())) {
                    return true;
                } else {
                    List<Long> templateIntroduce = templateIntroduceList.stream().map(resource -> resource.getPlanTemplateChapterId()).collect(Collectors.toList());
                    List<Long> planIntroduce = planIntroduceList.stream().map(resource -> resource.getPlanTemplateChapterId()).collect(Collectors.toList());
                    if (!templateIntroduce.containsAll(planIntroduce)) {
                        return true;
                    }
                }
            }

            /*||(templateChapter.getReferencesInfo() != null && chapterInstance.getReferencesInfo() == null)
                    || (templateChapter.getReferencesInfo() == null && chapterInstance.getReferencesInfo() != null)
                    || (templateChapter.getReferencesInfo() != null && chapterInstance.getReferencesInfo() != null
                    && (!Objects.equals(templateChapter.getReferencesInfo().getReferencesClassCode(), chapterInstance.getReferencesInfo().getReferencesClassCode())
                    || !templateChapter.getReferencesInfo().getReferencesCiCodes().containsAll(chapterInstance.getReferencesInfo().getReferencesCiCodes())));*/

            ChapterContext context = chapterContextDao.getById(chapterInstance.getId());
            if (!Objects.equals(templateChapter.getChapterDesc(), context.getChapterDesc())) {
                return true;
            }
            if (!Objects.equals(templateChapter.getRemarkInfo(), context.getRemark())) {
                return true;
            }
            String userAddContent = context.getUserAddContent() ? "1" : "0";
            if (!Objects.equals(userAddContent, templateChapter.getUserAddContent())) {
                return true;
            }
        }
        return null;
    }

    private void incrMethod(String diagramId,PlanArtifact planArtifact,Map<String, Set<Integer>> map) {
        if (map.containsKey(diagramId)) {
            Set<Integer> versions = map.get(diagramId);
            versions.add(planArtifact.getVersion());
            map.put(diagramId,versions);
        }else{
            Set<Integer> set = new HashSet();
            set.add(planArtifact.getVersion());
            map.put(diagramId,set);
        }
    }

    private String findChapterPathName(List<ChapterInstance> chapterInstanceList, ChapterInstance chapterInstance, String planTemplateChapterIdPath) {
        String[] planTemplateChapterIdArray = planTemplateChapterIdPath.split("/");
        List<String> planTemplateChapterIdList = Arrays.asList(planTemplateChapterIdArray);
        List<ChapterInstance> planChapterList = chapterInstanceList.stream().filter(item ->item.getIsFromTemplate().equals(true) && item.getPlanId().equals(chapterInstance.getPlanId()) && planTemplateChapterIdList.contains(item.getTemplateId().toString())).collect(Collectors.toList());
        Map<Long, String> planNameMap = planChapterList.stream().collect(Collectors.toMap(item -> item.getTemplateId(), item -> item.getName()));
        StringBuilder stringBuilder = new StringBuilder();
        //stringBuilder.append(chapterInstance.getName());
        for (String chapterId : planTemplateChapterIdList) {
            String chapterName = planNameMap.get(Long.valueOf(chapterId));
            stringBuilder.append("/"+chapterName);
        }
        return stringBuilder.toString();
    }

    /**
     * 方法名称：刷新序号
     * <p>使用场景</p>
     *
     * <ol>
     *     <li>新增章节</li>
     *     <li>删除章节</li>
     *     <li>移动章节</li>
     *     <li>复制章节</li>
     * </ol>
     *
     * @param parentId 父章节id
     * @param planId   方案id
     */
    private void refreshSort(Long parentId, Long planId) {
        String prefix;
        if (parentId == 0) {
            prefix = "";
        } else {
            ChapterInstance parentChapter = planChapterInstanceDao.getById(parentId);
            prefix = parentChapter.getSerialNum();
        }

        List<ChapterInstance> chapterList = new ArrayList<>();
        addSortedChapter(parentId, planId, prefix, chapterList);

        if (BinaryUtils.isEmpty(chapterList)) {
            return;
        }

        planChapterInstanceDao.saveOrUpdateBatch(chapterList);
    }

    private void addSortedChapter(Long parentId, Long planId, String prefix, List<ChapterInstance> chapterTotal) {
        List<ChapterInstance> chapterList = planChapterInstanceDao.getListByQuery(QueryBuilders.boolQuery()
                .must(QueryBuilders.termQuery("planId", planId))
                .must(QueryBuilders.termQuery("parentId", parentId))
                .must(QueryBuilders.termQuery("deleted", false)));

        if (BinaryUtils.isEmpty(chapterList)) {
            return;
        }

        // 排序 根据orderId
        chapterList = chapterList.stream().sorted((x, y) -> {
            BigDecimal a = new BigDecimal(x.getOrderId().toString());
            BigDecimal b = new BigDecimal(y.getOrderId().toString());
            return a.compareTo(b);
        }).collect(Collectors.toList());

        boolean prefixIsBlank = BinaryUtils.isEmpty(prefix);
        int i = 0;
        for (ChapterInstance chapter : chapterList) {
            String serialNum = prefixIsBlank ? Integer.toString(++i) : String.format("%s.%s", prefix, ++i);
            chapter.setSerialNum(serialNum);

            /*
            重新给orderId赋值是想提升这个值的可读性。
            因为，这个值经过各种排序后可能会出现负值、带小数的值，可读性就会降低
            所以，这里重新赋值后可消灭负值以及带小数的值，同时也提高了字段值的可读性
             */
            chapter.setOrderId((double) i);

            // 递归设置子节点
            addSortedChapter(chapter.getId(), planId, serialNum, chapterTotal);
        }

        chapterTotal.addAll(chapterList);
    }

    private void checkDel(ChapterInstance chapter) {
        List<PlanChapterVO> chapterList = getChapterList(chapter.getPlanId());
        List<PlanChapterVO> filterChapterList = chapterList.stream().filter(item -> item.getIsFromTemplate()).collect(Collectors.toList());
        if (filterChapterList.size() == 1 && chapter.getIsFromTemplate() && chapter.getParentId() == 0) {
            throw new BusinessException("模板章节不能全部删除");
        }
        log.info("chapterList:",chapterList);
        if (chapter.getIsFromTemplate() && !Objects.equals(chapter.getTemplateDelete(), 1)) {
            if (chapter.getRequired()) {
                throw new BusinessException(Constants.DEL_PLAN_CHAPTER_FAIL_MSG);
            } else {
                List<ChapterInstance> childChapterList = planChapterInstanceDao.getListByQuery(QueryBuilders.boolQuery()
                        .must(QueryBuilders.termQuery("planId", chapter.getPlanId()))
                        .must(QueryBuilders.termQuery("parentId", chapter.getId()))
                        .must(QueryBuilders.termQuery("deleted", false)));
                if (!BinaryUtils.isEmpty(childChapterList)) {
                    childChapterList.forEach(this::checkDel);
                }
            }
        }
    }

    private void doDelete(Long id) {
        BoolQueryBuilder builder = QueryBuilders.boolQuery();
        builder.must(QueryBuilders.termQuery("id", id));

        String script = String.format("ctx._source.deleted=%s", true);
        planChapterInstanceDao.updateByQuery(builder, script, true);
    }

    /**
     * 新增时 设置 层级 和 排序
     */
    private void setOrderIdAndLevel(ChapterInstance chapter) {
        Long parentId = chapter.getParentId();

        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery()
                .must(QueryBuilders.termQuery("planId", chapter.getPlanId()))
                .must(QueryBuilders.termQuery("parentId", parentId))
                .must(QueryBuilders.termQuery("deleted", false));

        Page<ChapterInstance> pageInfo = planChapterInstanceDao.getSortListByQuery(1, 1, boolQueryBuilder, "orderId",
                false);

        if (pageInfo.getTotalRows() >= 1) {
            ChapterInstance lastChapter = pageInfo.getData().get(0);
            chapter.setOrderId(lastChapter.getOrderId() + 1);
            chapter.setLevel(lastChapter.getLevel());
        } else if (parentId == 0) {
            chapter.setLevel(1);
            chapter.setOrderId(1D);
        } else {
            int level;
            int maxLevel = 8;
            ChapterInstance parentChapter = planChapterInstanceDao.getById(parentId);
            Integer parentLevel = parentChapter.getLevel();
            if ((level = parentLevel + 1) > maxLevel) {
                throw new BusinessException("超过最大层级");
            }
            chapter.setLevel(level);
            chapter.setOrderId(1D);
        }
    }

    /**
     * 移动时计算排序
     */
    private void setOrderId(int index, ChapterInstance chapter, Long parentId) {

        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery()
                .must(QueryBuilders.termQuery("parentId", parentId))
                .must(QueryBuilders.termQuery("planId", chapter.getPlanId()))
                .must(QueryBuilders.termQuery("deleted", false))
                .mustNot(QueryBuilders.termQuery("id", chapter.getId()));

        List<ChapterInstance> list = planChapterInstanceDao.getSortListByQuery(1, 3000,
                boolQueryBuilder, "orderId", true).getData();


        int maxIndex = list.size() - 1;
        int minIndex = 0;
        double orderId;

        if (BinaryUtils.isEmpty(list)) {
            orderId = 0;
        } else if (index == minIndex) {
            orderId = list.get(minIndex).getOrderId() - 1;
        } else if (index > maxIndex) {
            orderId = list.get(maxIndex).getOrderId() + 1;
        } else {
            Double leftOrderId = list.get(index - 1).getOrderId();
            Double rightOrderId = list.get(index).getOrderId();
            orderId = (leftOrderId + rightOrderId) / 2;
        }

        chapter.setOrderId(orderId);
    }

    /**
     * 生成VO 树形结构
     */
    private List<PlanChapterVO> createChapterVO(List<ChapterInstance> listByQuery, long parentId,
                                                Boolean expectedDetail) {
        List<ChapterInstance> list = listByQuery.stream().filter(instance ->instance.getParentId() != null && instance.getParentId() == parentId)
                .sorted((x, y) -> {
                    BigDecimal a = new BigDecimal(x.getOrderId().toString());
                    BigDecimal b = new BigDecimal(y.getOrderId().toString());
                    return a.compareTo(b);
                }).collect(Collectors.toList());

        return BinaryUtils.isEmpty(list) ? Collections.emptyList() : list.stream().map(instance -> {
            PlanChapterVO vo = new PlanChapterVO();
            BeanUtils.copyProperties(instance, vo);
            String fullName = String.format("%s %s", vo.getSerialNum(), vo.getName());
            vo.setFullName(fullName);
            vo.setExpand(true);
            if (expectedDetail) {
                ChapterContextVO contextVO = chapterContextService.findById(vo.getId());
                vo.setContext(contextVO);
            }

            // 查询章节是否已被加锁
            String key = Constants.LOCK_CHAPTER_SET + instance.getPlanId() + Constants.COLON + instance.getId() + Constants.COLON;
            String value = (String) iCacheService.getCache(key);
            if (!StringUtils.isEmpty(value)) {
                SysUser sysUser = SysUtil.getCurrentUserInfo();
                if (Objects.equals(value, sysUser.getLoginCode())) {
                    vo.setLock(0);
                } else {
                    vo.setLock(1);
                }
            } else {
                vo.setLock(0);
            }

            // 判断章节是否存在协作
            PlanChapterCollaborate planChapterCollaborate = new PlanChapterCollaborate();
            planChapterCollaborate.setPlanId(instance.getPlanId());
            planChapterCollaborate.setChapterId(instance.getId());
            PlanChapterCollaborate collaborate = planChapterCollaborateService.getPlanChapterCollaborate(planChapterCollaborate);
            if (collaborate != null && !CollectionUtils.isEmpty(collaborate.getShareMemberList())) {
                vo.setExistCollaborate(1);
            } else {
                vo.setExistCollaborate(0);
            }

            // 判断是否已完成章节协作
            String loginCode = SysUtil.getCurrentUserInfo().getLoginCode();
            if (!StringUtils.isEmpty(loginCode) && collaborate != null && Objects.equals(collaborate.getComplete(), 1)) {
                PlanDesignInstance planDesignInstance = planDesignInstanceService.getPlanDesignInstance(instance.getPlanId());
                List<SharedUserVO> planSharedMemberList = shareService.findPlanSharedList(instance.getPlanId(), false);

                if (planDesignInstance != null && Objects.equals(planDesignInstance.getCreatorCode(), loginCode)) {
                    vo.setCompleteCollaborate(1);
                    vo.setButtonSign(1);
                } else if (!CollectionUtils.isEmpty(planSharedMemberList)) {
                    List<String> collect = planSharedMemberList.stream()
                            .filter(sharedUserVO -> (Objects.equals(sharedUserVO.getPermission(), PlanSharePermissionEnum.EDIT_AND_SHARE.getFlag())
                                    || Objects.equals(sharedUserVO.getPermission(), PlanSharePermissionEnum.PUBLISH.getFlag()))
                                    && !StringUtils.isEmpty(sharedUserVO.getLoginCode()))
                            .map(SharedUserVO::getLoginCode).collect(Collectors.toList());
                    if (collect.contains(loginCode)) {
                        vo.setCompleteCollaborate(1);
                        vo.setButtonSign(1);
                    } else {
                        if (!CollectionUtils.isEmpty(collaborate.getShareMemberList())) {
                            if (collaborate.getShareMemberList().contains(loginCode)) {
                                vo.setCompleteCollaborate(1);
                                vo.setButtonSign(1);
                            }
                        }
                    }
                }  else {
                    if (!CollectionUtils.isEmpty(collaborate.getShareMemberList())) {
                        if (collaborate.getShareMemberList().contains(loginCode)) {
                            vo.setCompleteCollaborate(1);
                            vo.setButtonSign(1);
                        }
                    }
                }
            }

            // 递归调用
            List<PlanChapterVO> childChapterList = createChapterVO(listByQuery, vo.getId(), expectedDetail);
            vo.setChildChapterList(childChapterList);
            return vo;
        }).collect(Collectors.toList());
    }

    /**
     * 生成章节
     *
     * @param chapterList  生成的章节存在这个字段
     * @param contextList  根据模板生成的章节数据保存在这个字段
     * @param templateList 章节模板集合
     * @param planId       所属方案id
     * @param date         时间
     * @param sysUser      当前用户信息
     */
    private void createChapter(List<ChapterInstance> chapterList, List<ChapterContext> contextList,
                               List<PlanTemplateChapterTreeVo> templateList, Long planId, Long date,
                               SysUser sysUser) {

        doCreateChapter(chapterList, contextList, templateList, planId, 0L, date, sysUser);

        // 设置章节显示的序号，例如“1.1.1 EA架构图”
        setSerialNum(chapterList, 0L, "");
    }

    private void doCreateChapter(List<ChapterInstance> chapterList, List<ChapterContext> contextList,
                                 List<PlanTemplateChapterTreeVo> templateList, Long planId, Long parentId, Long date,
                                 SysUser sysUser) {
        for (PlanTemplateChapterTreeVo nodeTemplate : templateList) {
            // 章节id
            long id = ESUtil.getUUID();
            PlanTemplateChapterDataVo templateVO =
                    planTemplateChapterService.getPlanTemplateChapter(nodeTemplate.getId());

            PlanTemplateChapter contextTemplate = templateVO.getChapter();
            String chapterDesc = contextTemplate.getChapterDesc();
            Boolean required = "1".equals(contextTemplate.getRequired());
            Boolean userAddContent = "1".equals(contextTemplate.getUserAddContent());
            ChapterInstance build = ChapterInstance.builder()
                    .id(id)
                    .isFromTemplate(true)
                    .name(nodeTemplate.getChapterName())
                    .level(nodeTemplate.getLevel())
                    .orderId(nodeTemplate.getSortNum())
                    .expand(nodeTemplate.isExpand())
                    .parentId(parentId)
                    .planId(planId)
                    .required(required)
                    .templateId(nodeTemplate.getId())
                    .templateParentId(nodeTemplate.getParentId())
                    .deleted(false).build();
            build.setCreatorCode(sysUser.getLoginCode());
            build.setCreatorName(sysUser.getUserName());
            build.setCreateTime(date);
            List<ChapterResource> planResource = cjResourceDaoService.getPlanResource(nodeTemplate.getPlanTemplateId(), nodeTemplate.getId());
            build.setChapterResources(planResource);
            build.setPlanTemplateIntroduceChapterVoList(nodeTemplate.getPlanTemplateIntroduceChapterVoList());

            // 章节基本信息
            chapterList.add(build);

            // 章节context
            ChapterContext chapterContext = ChapterContext.builder()
                    .id(id)
                    .planId(planId)
                    .chapterDesc(chapterDesc)
                    .userAddContent(userAddContent)
                    .remark(contextTemplate.getRemarkInfo())
                    .moduleList(new LinkedList<>()).build();

            contextList.add(chapterContext);

            List<PlanTemplateChapterData> chapterDataPage = planTemplateChapterService.findChapterDataList(nodeTemplate.getId());
            // 章节module
            if (!BinaryUtils.isEmpty(chapterDataPage)) {

                chapterContext.getModuleList().addAll(chapterDataPage.stream()
                        .map(vo -> {
                            ContextModule contextModule = new ContextModule();
                            contextModule.setId(vo.getId());
                            if (Objects.equals(vo.getType(), ChapterDataTypeEnum.RICH_TEXT.getDataType()) && !StringUtils.isEmpty(vo.getInitRichText())) {
                                JSONObject jsonObject = new JSONObject();
                                jsonObject.put("data", vo.getInitRichText());
                                contextModule.setData(jsonObject.toJSONString());
                            } else {
                                contextModule.setData("{}");
                            }
                            contextModule.setIsFromTemplate(true);
                            contextModule.setModuleDefinition(vo);
                            return contextModule;
                        }).collect(Collectors.toList()));
            }

            // 子章节
            List<PlanTemplateChapterTreeVo> child = nodeTemplate.getChild();
            if (!BinaryUtils.isEmpty(child)) {
                doCreateChapter(chapterList, contextList, child, planId, id, date, sysUser);
            }
        }
    }

    /**
     * 设置章节显示的序号
     *
     * @param chapterList 所有章节
     * @param parentId    父章节id
     * @param prefix      序号前缀
     */
    private void setSerialNum(List<ChapterInstance> chapterList, Long parentId, String prefix) {
        List<ChapterInstance> chapterInstanceList =
                chapterList.stream().filter(chapterInstance -> chapterInstance.getParentId().equals(parentId)).collect(Collectors.toList());

        if (BinaryUtils.isEmpty(chapterInstanceList)) {
            return;
        }

        boolean prefixIsBlank = BinaryUtils.isEmpty(prefix);
        int i = 0;
        for (ChapterInstance instance : chapterInstanceList) {
            String serialNum = prefixIsBlank ? Integer.toString(++i) : String.format("%s.%s", prefix, ++i);
            instance.setSerialNum(serialNum);

            // 递归设置子章节
            setSerialNum(chapterList, instance.getId(), instance.getSerialNum());
        }
    }
}

